home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 015a / memsz160.zip / MEMSIZE.C < prev    next >
C/C++ Source or Header  |  1993-03-08  |  125KB  |  3,837 lines

  1. /****************************************************************** MEMSIZE.C
  2.  *                                        *
  3.  * System Resources Monitor                            *
  4.  *                                        *
  5.  * Revision 1.60 (08 March 1993)                        *
  6.  *                                        *
  7.  * (C) Copyright 1991-1993 by Richard W. Papo.                    *
  8.  *                                        *
  9.  * This is 'FreeWare'.    As such, it may be copied and distributed        *
  10.  * freely.  If you want to use part of it in your own program, please        *
  11.  * give credit where credit is due.  If you want to change the            *
  12.  * program, please refer the change request to me or send me the        *
  13.  * modified source code.  I can be reached at CompuServe 72607,3111.        *
  14.  *                                        *
  15.  ****************************************************************************/
  16.  
  17. #define INCL_BASE
  18. #define INCL_PM
  19. #include <os2.h>
  20.  
  21. #include <direct.h>
  22. #include <process.h>
  23. #include <stdarg.h>
  24. #include <stddef.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <time.h>
  29.  
  30. #include <sys\types.h>
  31. #include <sys\stat.h>
  32.  
  33. #include "debug.h"
  34. #include "support.h"
  35. #include "about.h"
  36. #include "settimer.h"
  37.  
  38. #include "memsize.h"
  39.  
  40.  
  41. /****************************************************************************
  42.  *                                        *
  43.  *             Definitions & Declarations                *
  44.  *                                        *
  45.  ****************************************************************************/
  46.  
  47.   // Constants
  48.  
  49. #define PROGRAM_NAME        "MEMSIZE"
  50. #define CLASS_NAME        "MEMSIZE"
  51.  
  52. enum
  53. {
  54.   ITEM_CLOCK,
  55.   ITEM_MEMORYFREE,
  56.   ITEM_SWAPFILESIZE,
  57.   ITEM_SWAPDISKFREE,
  58.   ITEM_SPOOLFILESIZE,
  59.   ITEM_CPULOAD,
  60.   ITEM_TASKCOUNT,
  61.   ITEM_BASE_COUNT
  62. } ;
  63.  
  64. #define WM_REFRESH        WM_USER
  65.  
  66. #define MAX_DRIVES      26
  67. #define DRIVE_ERROR      0xFFFFFFFFL
  68.  
  69.  
  70.   // Data Types
  71.  
  72. typedef struct          // Data structure for item to be monitored.
  73. {
  74.   CHAR     Name [80] ;           // Text for item's profile name.
  75.   BOOL     Flag ;            // Flag: Show this item at this time?
  76.   CHAR     Label [80] ;           // Text to display on left part of line.
  77.   ULONG  Value ;           // Value to display on right part of line.
  78.   CHAR     MenuOption [80] ;     // Text to display in system menu.
  79.   USHORT MenuId ;           // ID for use in system menu.
  80.   ULONG  (*NewValue)           // Function to determine new value.
  81.     (PVOID,USHORT) ;
  82.   USHORT Parm ;            // Parameter to pass to NewValue function.
  83.   USHORT Divisor ;           // Amount to divide value by before display.
  84.   CHAR     Suffix ;           // Character to place after value.
  85. }
  86. ITEM, *PITEM ;
  87.  
  88. typedef struct          // Parameters saved to system.
  89. {
  90.   PITEM  Items ;        // Items to display.
  91.   int     ItemCount ;
  92.  
  93.   SWP     Position ;        // Window size & location.
  94.   BOOL     fPosition ;
  95.  
  96.   BOOL     HideControls ;     // User options.
  97.   BOOL     fHideControls ;
  98.  
  99.   USHORT TimerInterval ;
  100.   BOOL     fTimerInterval ;
  101.  
  102.   CHAR     FontNameSize [80] ;    // Presentation Parameters
  103.   BOOL     fFontNameSize ;
  104.  
  105.   COLOR  BackColor ;
  106.   BOOL     fBackColor ;
  107.  
  108.   COLOR  TextColor ;
  109.   BOOL     fTextColor ;
  110. }
  111. PROFILE, *PPROFILE ;
  112.  
  113. typedef struct        // Data structure for window.
  114. {
  115.   HAB         Anchor ;
  116.   HMODULE     Library ;
  117.  
  118.   ULONG      MaxCount ;
  119.   ULONG      IdleCounter ;
  120.   ULONG      IdleCount ;
  121.   TID         IdleLoopTID ;
  122.   TID         MonitorLoopTID ;
  123.  
  124.   PROFILE     Profile ;
  125.  
  126.   HWND           hwndTitleBar ;
  127.   HWND           hwndSysMenu ;
  128.   HWND         hwndMinMax ;
  129.  
  130.   ULONG      Drives ;
  131.  
  132.   char           SwapPath [_MAX_PATH] ;
  133.   int         MinFree ;
  134.  
  135.   PCHAR      SpoolPath ;
  136.  
  137.   long         Width ;
  138.   long         Height ;
  139.  
  140.   COUNTRYINFO     CountryInfo ;
  141. }
  142. DATA, *PDATA ;
  143.  
  144. typedef struct
  145. {
  146.   HAB Anchor ;
  147.   HMODULE Library ;
  148. }
  149. PARMS, *PPARMS ;
  150.  
  151. typedef struct
  152. {
  153.   volatile PULONG Counter ;
  154.   PUSHORT Interval ;
  155.   HWND Owner ;
  156. }
  157. MONITOR_PARMS, *PMONITOR_PARMS ;
  158.  
  159.  
  160.   // Function Prototypes
  161.  
  162. extern void main ( int argc, PCHAR argv[] ) ;
  163.  
  164. static MRESULT EXPENTRY MessageProcessor
  165. (
  166.   HWND hwnd,
  167.   USHORT msg,
  168.   MPARAM mp1,
  169.   MPARAM mp2
  170. ) ;
  171.  
  172. static METHODFUNCTION Create ;
  173. static METHODFUNCTION Destroy ;
  174. static METHODFUNCTION Size ;
  175. static METHODFUNCTION SaveApplication ;
  176. static METHODFUNCTION Paint ;
  177. static METHODFUNCTION Command ;
  178. static METHODFUNCTION ResetDefaults ;
  179. static METHODFUNCTION HideControlsCmd ;
  180. static METHODFUNCTION SetTimer ;
  181. static METHODFUNCTION About ;
  182. static METHODFUNCTION ButtonDown ;
  183. static METHODFUNCTION ButtonDblClick ;
  184. static METHODFUNCTION PresParamChanged ;
  185. static METHODFUNCTION SysColorChange ;
  186. static METHODFUNCTION QueryKeysHelp ;
  187. static METHODFUNCTION HelpError ;
  188. static METHODFUNCTION ExtHelpUndefined ;
  189. static METHODFUNCTION HelpSubitemNotFound ;
  190. static METHODFUNCTION Refresh ;
  191.  
  192. static void GetProfile ( HAB Anchor, HMODULE Library, PPROFILE Profile ) ;
  193. static void PutProfile ( PPROFILE Profile ) ;
  194.  
  195. static PCHAR ScanSystemConfig ( PCHAR Keyword ) ;
  196.  
  197. static void ResizeWindow ( HWND hwnd, PPROFILE Profile ) ;
  198.  
  199. static void HideControls
  200. (
  201.   BOOL fHide,
  202.   HWND hwndFrame,
  203.   HWND hwndSysMenu,
  204.   HWND hwndTitleBar,
  205.   HWND hwndMinMax
  206. ) ;
  207.  
  208. static void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All ) ;
  209.  
  210. static ULONG ComputeTime       ( PDATA Data, USHORT Dummy ) ;
  211. static ULONG ComputeFreeMemory ( PDATA Data, USHORT Dummy ) ;
  212. static ULONG ComputeSwapSize   ( PDATA Data, USHORT Dummy ) ;
  213. static ULONG ComputeSwapFree   ( PDATA Data, USHORT Dummy ) ;
  214. static ULONG ComputeSpoolSize  ( PDATA Data, USHORT Dummy ) ;
  215. static ULONG ComputeCpuLoad    ( PDATA Data, USHORT Dummy ) ;
  216. static ULONG ComputeTaskCount  ( PDATA Data, USHORT Dummy ) ;
  217. static ULONG ComputeDriveFree  ( PDATA Data, USHORT Drive ) ;
  218.  
  219. static void _far _cdecl MonitorLoopThread ( PMONITOR_PARMS Parms ) ;
  220.  
  221. static VOID UpdateDriveList
  222. (
  223.   HAB Anchor,
  224.   HMODULE Library,
  225.   PPROFILE Profile,
  226.   ULONG OldDrives
  227. ) ;
  228.  
  229. static BOOL CheckDrive ( USHORT Drive ) ;
  230.  
  231. static VOID RebuildDisplayItems ( HWND hwnd, PDATA Data ) ;
  232.  
  233. static ULONG CalibrateLoadMeter ( void ) ;
  234.  
  235. static void _far _cdecl CounterThread ( PULONG Counter ) ;
  236.  
  237.  
  238.   // Global Data (private)
  239.  
  240. static ITEM Items [ ITEM_BASE_COUNT + MAX_DRIVES ] =
  241. {
  242.   {
  243.     "ShowTime",      TRUE, "", 0L, "", IDM_SHOW_CLOCK,
  244.     ComputeTime,       0,    0, ' '
  245.   },
  246.  
  247.   {
  248.     "ShowMemory",    TRUE, "", 0L, "", IDM_SHOW_MEMORY,
  249.     ComputeFreeMemory, 0, 1024, 'K'
  250.   },
  251.  
  252.   {
  253.     "ShowSwapsize",  TRUE, "", 0L, "", IDM_SHOW_SWAPSIZE,
  254.     ComputeSwapSize,   0, 1024, 'K'
  255.   },
  256.  
  257.   {
  258.     "ShowSwapfree",  TRUE, "", 0L, "", IDM_SHOW_SWAPFREE,
  259.     ComputeSwapFree,   0, 1024, 'K'
  260.   },
  261.  
  262.   {
  263.     "ShowSpoolSize", TRUE, "", 0L, "", IDM_SHOW_SPOOLSIZE,
  264.     ComputeSpoolSize,  0, 1024, 'K'
  265.   },
  266.  
  267.   {
  268.     "ShowCpuLoad",   TRUE, "", 0L, "", IDM_SHOW_CPULOAD,
  269.     ComputeCpuLoad,    0,    0, '%'
  270.   },
  271.  
  272.   {
  273.     "ShowTaskCount", TRUE, "", 0L, "", IDM_SHOW_TASKCOUNT,
  274.     ComputeTaskCount,  0,    0, ' '
  275.   }
  276. } ;
  277.  
  278.  
  279. /****************************************************************************
  280.  *                                        *
  281.  *    Program Mainline                            *
  282.  *                                        *
  283.  ****************************************************************************/
  284.  
  285. extern void main ( int argc, PCHAR argv[] )
  286. {
  287.  /***************************************************************************
  288.   * Local Declarations                                *
  289.   ***************************************************************************/
  290.  
  291.   HELPINIT HelpInit =
  292.   {
  293.     sizeof ( HELPINIT ),
  294.     0L,
  295.     NULL,
  296.     MAKEP ( 0xFFFF, ID_MAIN ),
  297.     0,
  298.     0,
  299.     0,
  300.     0,
  301.     NULL,
  302.     CMIC_HIDE_PANEL_ID,
  303.     PROGRAM_NAME ".HLP"
  304.   } ;
  305.  
  306.   HAB Anchor ;
  307.   FRAMECDATA fcdata ;
  308.   CHAR HelpTitle [80] ;
  309.   HWND hwndClient ;
  310.   HWND hwndFrame ;
  311.   HWND hwndHelp ;
  312.   HMODULE Library ;
  313.   HMQ MessageQueue ;
  314.   PARMS Parms ;
  315.   QMSG QueueMessage ;
  316.   BOOL Reset ;
  317.   CHAR ResetCommand [40] ;
  318.   CHAR Title [80] ;
  319.  
  320.  /***************************************************************************
  321.   * Initialize for PM.    Abort if unable to do so.                *
  322.   ***************************************************************************/
  323.  
  324.   Anchor = WinInitialize ( 0 ) ;
  325.   if ( Anchor == NULL )
  326.     return ;
  327.  
  328.  /***************************************************************************
  329.   * Create the application message queue.  Abort if unable to do so.        *
  330.   ***************************************************************************/
  331.  
  332.   MessageQueue = WinCreateMsgQueue ( Anchor, 0 ) ;
  333.   if ( MessageQueue == NULL )
  334.   {
  335.     WinTerminate ( Anchor ) ;
  336.     return ;
  337.   }
  338.  
  339.  /***************************************************************************
  340.   * Now WIN and GPI calls will work.  Open the language DLL.            *
  341.   ***************************************************************************/
  342.  
  343.   if ( DosLoadModule ( NULL, 0, PROGRAM_NAME, &Library ) )
  344.   {
  345.     Debug ( HWND_DESKTOP, "ERROR: Unable to load " PROGRAM_NAME ".DLL." ) ;
  346.     WinDestroyMsgQueue ( MessageQueue ) ;
  347.     WinTerminate ( Anchor ) ;
  348.     return ;
  349.   }
  350.  
  351.  /***************************************************************************
  352.   * Register the window class.                            *
  353.   ***************************************************************************/
  354.  
  355.   if ( NOT WinRegisterClass ( Anchor, CLASS_NAME, MessageProcessor,
  356.     CS_MOVENOTIFY, sizeof(PVOID) ) )
  357.   {
  358.     CHAR Message [200] ;
  359.     char Title [80] ;
  360.  
  361.     WinLoadString ( Anchor, Library, IDS_TITLE,
  362.       sizeof(Title), Title ) ;
  363.     WinLoadString ( Anchor, Library, IDS_ERROR_WINREGISTERCLASS,
  364.       sizeof(Message), Message ) ;
  365.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  366.       Title, 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  367.  
  368.     WinDestroyMsgQueue ( MessageQueue ) ;
  369.     WinTerminate ( Anchor ) ;
  370.     return ;
  371.   }
  372.  
  373.  /***************************************************************************
  374.   * Decipher command-line parameters.                        *
  375.   ***************************************************************************/
  376.  
  377.   WinLoadString ( Anchor, Library, IDS_PARMS_RESET, sizeof(ResetCommand), ResetCommand ) ;
  378.   Reset = FALSE ;
  379.  
  380.   while ( --argc )
  381.   {
  382.     argv ++ ;
  383.     strupr ( *argv ) ;
  384.     if ( *argv[0] == '?' )
  385.     {
  386.       CHAR Message [200] ;
  387.       CHAR Title [80] ;
  388.  
  389.       WinLoadString ( Anchor, Library, IDS_TITLE,
  390.     sizeof(Title), Title ) ;
  391.       WinLoadString ( Anchor, Library, IDS_PARAMETERLIST,
  392.     sizeof(Message), Message ) ;
  393.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  394.     Title, 0, MB_ENTER | MB_NOICON ) ;
  395.  
  396.       WinDestroyMsgQueue ( MessageQueue ) ;
  397.       WinTerminate ( Anchor ) ;
  398.       return ;
  399.     }
  400.  
  401.     if ( !strcmp ( *argv, ResetCommand ) )
  402.     {
  403.       Reset = TRUE ;
  404.       continue ;
  405.     }
  406.  
  407.     {
  408.       CHAR Format [200] ;
  409.       CHAR Message [200] ;
  410.       CHAR Title [80] ;
  411.  
  412.       WinLoadString ( Anchor, Library, IDS_TITLE,
  413.     sizeof(Title), Title ) ;
  414.       WinLoadString ( Anchor, Library, IDS_ERROR_INVALIDPARM,
  415.     sizeof(Format), Format ) ;
  416.       sprintf ( Message, Format, *argv ) ;
  417.       WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  418.     Title, 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  419.  
  420.       WinDestroyMsgQueue ( MessageQueue ) ;
  421.       WinTerminate ( Anchor ) ;
  422.       return ;
  423.     }
  424.   }
  425.  
  426.  /***************************************************************************
  427.   * If we're going to reset the program's profile, do it now.               *
  428.   ***************************************************************************/
  429.  
  430.   if ( Reset )
  431.   {
  432.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, NULL, NULL, 0 ) ;
  433.   }
  434.  
  435.  /***************************************************************************
  436.   * Create the help instance.                            *
  437.   ***************************************************************************/
  438.  
  439.   WinLoadString ( Anchor, Library, IDS_HELPTITLE, sizeof(HelpTitle), HelpTitle ) ;
  440.   HelpInit.pszHelpWindowTitle = HelpTitle ;
  441.  
  442.   hwndHelp = WinCreateHelpInstance ( Anchor, &HelpInit ) ;
  443.  
  444.   if ( hwndHelp == NULL )
  445.   {
  446.     CHAR Message [200] ;
  447.     char Title [80] ;
  448.  
  449.     WinLoadString ( Anchor, Library, IDS_TITLE,
  450.       sizeof(Title), Title ) ;
  451.     WinLoadString ( Anchor, Library, IDS_ERROR_WINCREATEHELPINSTANCE,
  452.       sizeof(Message), Message ) ;
  453.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  454.       Title, 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  455.   }
  456.  
  457.  /***************************************************************************
  458.   * Create the frame window.                            *
  459.   ***************************************************************************/
  460.  
  461.   fcdata.cb = sizeof(fcdata) ;
  462.   fcdata.flCreateFlags =
  463.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  464.       FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE ;
  465.   fcdata.hmodResources = 0 ;
  466.   fcdata.idResources   = ID_MAIN ;
  467.  
  468.   hwndFrame = WinCreateWindow
  469.   (
  470.     HWND_DESKTOP,
  471.     WC_FRAME,
  472.     "",
  473.     0,
  474.     0, 0, 0, 0,
  475.     HWND_DESKTOP,
  476.     HWND_TOP,
  477.     ID_MAIN,
  478.     &fcdata,
  479.     NULL
  480.   ) ;
  481.  
  482.   if ( hwndFrame == NULL )
  483.   {
  484.     CHAR Message [200] ;
  485.     char Title [80] ;
  486.  
  487.     WinLoadString ( Anchor, Library, IDS_TITLE,
  488.       sizeof(Title), Title ) ;
  489.     WinLoadString ( Anchor, Library, IDS_ERROR_WINCREATEFRAME,
  490.       sizeof(Message), Message ) ;
  491.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  492.       Title, 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  493.  
  494.     WinDestroyMsgQueue ( MessageQueue ) ;
  495.     WinTerminate ( Anchor ) ;
  496.     return ;
  497.   }
  498.  
  499.  /***************************************************************************
  500.   * Set the title.                                *
  501.   ***************************************************************************/
  502.  
  503.   WinLoadString ( Anchor, Library, IDS_TITLE, sizeof(Title), Title ) ;
  504.   WinSetWindowText ( hwndFrame, Title ) ;
  505.  
  506.  /***************************************************************************
  507.   * Associate the help instance with the frame window.                *
  508.   ***************************************************************************/
  509.  
  510.   if ( hwndHelp )
  511.   {
  512.     WinAssociateHelpInstance ( hwndHelp, hwndFrame ) ;
  513.   }
  514.  
  515.  /***************************************************************************
  516.   * Create client window.  If this fails, destroy frame and return.        *
  517.   ***************************************************************************/
  518.  
  519.   Parms.Anchor = Anchor ;
  520.   Parms.Library = Library ;
  521.  
  522.   hwndClient = WinCreateWindow
  523.   (
  524.     hwndFrame,
  525.     CLASS_NAME,
  526.     "",
  527.     0,
  528.     0, 0, 0, 0,
  529.     hwndFrame,
  530.     HWND_BOTTOM,
  531.     FID_CLIENT,
  532.     &Parms,
  533.     NULL
  534.   ) ;
  535.  
  536.   if ( hwndClient == NULL )
  537.   {
  538.     CHAR Message [200] ;
  539.     char Title [80] ;
  540.  
  541.     WinLoadString ( Anchor, Library, IDS_TITLE,
  542.       sizeof(Title), Title ) ;
  543.     WinLoadString ( Anchor, Library, IDS_ERROR_WINCREATEWINDOW,
  544.       sizeof(Message), Message ) ;
  545.     WinMessageBox ( HWND_DESKTOP, HWND_DESKTOP, Message,
  546.       Title, 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  547.  
  548.     WinDestroyWindow ( hwndFrame ) ;
  549.     WinDestroyMsgQueue ( MessageQueue ) ;
  550.     WinTerminate ( Anchor ) ;
  551.     return ;
  552.   }
  553.  
  554.  /***************************************************************************
  555.   * Wait for and process messages to the window's queue.  Terminate         *
  556.   *   when the WM_QUIT message is received.                    *
  557.   ***************************************************************************/
  558.  
  559.   while ( WinGetMsg ( Anchor, &QueueMessage, NULL, 0, 0 ) )
  560.   {
  561.     WinDispatchMsg ( Anchor, &QueueMessage ) ;
  562.   }
  563.  
  564.  /***************************************************************************
  565.   * Destroy the window.                             *
  566.   ***************************************************************************/
  567.  
  568.   WinDestroyWindow ( hwndFrame ) ;
  569.  
  570.  /***************************************************************************
  571.   * If help instance has been created, get rid of it.                *
  572.   ***************************************************************************/
  573.  
  574.   if ( hwndHelp )
  575.   {
  576.     WinDestroyHelpInstance ( hwndHelp ) ;
  577.   }
  578.  
  579.  /***************************************************************************
  580.   * Release the library, if one's been loaded.                              *
  581.   ***************************************************************************/
  582.  
  583.   if ( Library )
  584.   {
  585.     DosFreeModule ( Library ) ;
  586.   }
  587.  
  588.  /***************************************************************************
  589.   * Discard all that was requested of the system and terminate.         *
  590.   ***************************************************************************/
  591.  
  592.   WinDestroyMsgQueue ( MessageQueue ) ;
  593.  
  594.   WinTerminate ( Anchor ) ;
  595. }
  596.  
  597. /****************************************************************************
  598.  *                                        *
  599.  *    Window Message Processor                        *
  600.  *                                        *
  601.  ****************************************************************************/
  602.  
  603. static MRESULT EXPENTRY MessageProcessor
  604. (
  605.   HWND hwnd,
  606.   USHORT msg,
  607.   MPARAM mp1,
  608.   MPARAM mp2
  609. )
  610. {
  611.  /***************************************************************************
  612.   * Local Declarations                                *
  613.   ***************************************************************************/
  614.  
  615.   static METHOD Methods [] =
  616.   {
  617.     { WM_CREATE,        Create            },
  618.     { WM_DESTROY,        Destroy         },
  619.     { WM_SIZE,            Size            },
  620.     { WM_MOVE,            Size            },
  621.     { WM_SAVEAPPLICATION,    SaveApplication     },
  622.     { WM_PAINT,         Paint            },
  623.     { WM_BUTTON1DOWN,        ButtonDown        },
  624.     { WM_BUTTON2DOWN,        ButtonDown        },
  625.     { WM_BUTTON1DBLCLK,     ButtonDblClick        },
  626.     { WM_BUTTON2DBLCLK,     ButtonDblClick        },
  627.     { WM_PRESPARAMCHANGED,    PresParamChanged    },
  628.     { WM_SYSCOLORCHANGE,    SysColorChange        },
  629.     { WM_COMMAND,        Command         },
  630.     { HM_QUERY_KEYS_HELP,    QueryKeysHelp        },
  631.     { HM_ERROR,         HelpError        },
  632.     { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  633.     { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound },
  634.     { WM_REFRESH,        Refresh         }
  635.   } ;
  636.  
  637.  /***************************************************************************
  638.   * Dispatch the message according to the method table and return the        *
  639.   *   result.  Any messages not defined above get handled by the system     *
  640.   *   default window processor.                         *
  641.   ***************************************************************************/
  642.  
  643.   return ( DispatchMessage ( hwnd, msg, mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), WinDefWindowProc ) ) ;
  644. }
  645.  
  646. /****************************************************************************
  647.  *                                        *
  648.  *    Create the main window.                         *
  649.  *                                        *
  650.  ****************************************************************************/
  651.  
  652. static MRESULT APIENTRY Create
  653. (
  654.   HWND hwnd,
  655.   USHORT msg,
  656.   MPARAM mp1,
  657.   MPARAM mp2
  658. )
  659. {
  660.  /***************************************************************************
  661.   *                Declarations                    *
  662.   ***************************************************************************/
  663.  
  664.   static MENUITEM MenuItems [] =
  665.   {
  666.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, NULL, 0 },
  667.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   NULL, 0 },
  668.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    NULL, 0 },
  669.     { MIT_END, MIS_TEXT,      0, IDM_SET_TIMER,        NULL, 0 },
  670.     { MIT_END, MIS_SUBMENU,   0, IDM_DISPLAY_ITEMS,    NULL, 0 },
  671.   } ;
  672.  
  673.   static MENUITEM MenuSeparator =
  674.     { MIT_END, MIS_SEPARATOR, 0, 0, NULL, 0 } ;
  675.  
  676.   static MENUITEM MenuAbout =
  677.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, NULL, 0 } ;
  678.  
  679.   static MENUITEM MenuHelp =
  680.     { MIT_END, MIS_HELP, 0, 0, NULL, 0 } ;
  681.  
  682.   static MENUITEM MenuItem =
  683.     { MIT_END, MIS_TEXT, 0, 0, NULL, 0 } ;
  684.  
  685.   char AboutText [80] ;
  686.   PDATA Data ;
  687.   USHORT Drive ;
  688.   char HelpText [80] ;
  689.   HPS hPS ;
  690.   HWND hwndFrame ;
  691.   SHORT i ;
  692.   PMONITOR_PARMS MonitorParms ;
  693.   PPARMS Parms ;
  694.   RECTL Rectangle ;
  695.   ULONG Size ;
  696.   PCHAR Swappath ;
  697.   char Title [80] ;
  698.  
  699.  /***************************************************************************
  700.   * Allocate instance data.                            *
  701.   ***************************************************************************/
  702.  
  703.   Data = malloc ( sizeof(DATA) ) ;
  704.  
  705.   memset ( Data, 0, sizeof(DATA) ) ;
  706.  
  707.   WinSetWindowPtr ( hwnd, QWL_USER, Data ) ;
  708.  
  709.  /***************************************************************************
  710.   * Grab any parameters from the WM_CREATE message.                *
  711.   ***************************************************************************/
  712.  
  713.   Parms = (PPARMS) PVOIDFROMMP ( mp1 ) ;
  714.  
  715.   Data->Anchor = Parms->Anchor ;
  716.   Data->Library = Parms->Library ;
  717.  
  718.  /***************************************************************************
  719.   * Get the current drive mask.                         *
  720.   ***************************************************************************/
  721.  
  722.   DosQCurDisk ( &Drive, &Data->Drives ) ;
  723.  
  724.  /***************************************************************************
  725.   * Get profile data.                                *
  726.   ***************************************************************************/
  727.  
  728.   GetProfile ( Data->Anchor, Data->Library, &Data->Profile ) ;
  729.  
  730.  /***************************************************************************
  731.   * Get country information.                            *
  732.   ***************************************************************************/
  733.  
  734.   {
  735.     COUNTRYCODE CountryCode ;
  736.     USHORT Count ;
  737.     USHORT Status ;
  738.  
  739.     CountryCode.country = 0 ;
  740.     CountryCode.codepage = 0 ;
  741.  
  742.     Status = DosGetCtryInfo ( sizeof(Data->CountryInfo), &CountryCode,
  743.       &Data->CountryInfo, &Count ) ;
  744.     if ( Status )
  745.     {
  746.       char Message [80] ;
  747.       WinLoadMessage ( Data->Anchor, Data->Library, IDS_ERROR_DOSGETCTRYINFO,
  748.     sizeof(Message), Message ) ;
  749.       Debug ( hwnd, Message, Status ) ;
  750.       Data->CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  751.       Data->CountryInfo.fsTimeFmt = 0 ;
  752.       Data->CountryInfo.szDateSeparator[0] = '/' ;
  753.       Data->CountryInfo.szDateSeparator[1] = 0 ;
  754.       Data->CountryInfo.szTimeSeparator[0] = ':' ;
  755.       Data->CountryInfo.szTimeSeparator[1] = 0 ;
  756.       Data->CountryInfo.szThousandsSeparator[0] = ',' ;
  757.       Data->CountryInfo.szThousandsSeparator[1] = 0 ;
  758.     }
  759.   }
  760.  
  761.  /***************************************************************************
  762.   * Get the frame handle.                            *
  763.   ***************************************************************************/
  764.  
  765.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  766.  
  767.  /***************************************************************************
  768.   * Get the control window handles.                        *
  769.   ***************************************************************************/
  770.  
  771.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  772.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  773.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  774.  
  775.  /***************************************************************************
  776.   * Create the submenu window for Display Items.                *
  777.   ***************************************************************************/
  778.  
  779.   {
  780.     MENUITEM MenuItem ;
  781.     HWND hwndSysSubMenu ;
  782.     HWND hwndSubMenu ;
  783.     SHORT idSysMenu ;
  784.  
  785.     idSysMenu = SHORT1FROMMR ( WinSendMsg ( Data->hwndSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL ) ) ;
  786.     WinSendMsg ( Data->hwndSysMenu, MM_QUERYITEM, MPFROM2SHORT(idSysMenu,FALSE), MPFROMP(&MenuItem) ) ;
  787.     hwndSysSubMenu = MenuItem.hwndSubMenu ;
  788.  
  789.     hwndSubMenu = WinCreateWindow ( hwndSysSubMenu, WC_MENU, "",
  790.       WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  791.       0, 0, 0, 0, hwndSysSubMenu, HWND_TOP, IDM_DISPLAY_ITEMS, NULL, NULL ) ;
  792.  
  793.     MenuItems[IDM_DISPLAY_ITEMS-MenuItems[0].id].hwndSubMenu = hwndSubMenu ;
  794.   }
  795.  
  796.  /***************************************************************************
  797.   * Add basic extensions to the system menu.                    *
  798.   ***************************************************************************/
  799.  
  800.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  801.  
  802.   for ( i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  803.   {
  804.     char MenuText [80] ;
  805.     WinLoadString ( Data->Anchor, Data->Library, i+IDS_SAVE_APPLICATION, sizeof(MenuText), MenuText ) ;
  806.     AddSysMenuItem ( hwndFrame, MenuItems+i, MenuText ) ;
  807.   }
  808.  
  809.  /***************************************************************************
  810.   * Add 'About' to the system menu.                        *
  811.   ***************************************************************************/
  812.  
  813.   AddSysMenuItem ( hwndFrame, &MenuSeparator, NULL ) ;
  814.   WinLoadString ( Data->Anchor, Data->Library, IDS_ABOUT, sizeof(AboutText), AboutText ) ;
  815.   AddSysMenuItem ( hwndFrame, &MenuAbout, AboutText ) ;
  816.  
  817.  /***************************************************************************
  818.   * Add 'Help' to the system menu.                        *
  819.   ***************************************************************************/
  820.  
  821.   WinLoadString ( Data->Anchor, Data->Library, IDS_HELP, sizeof(HelpText), HelpText ) ;
  822.   AddSysMenuItem ( hwndFrame, &MenuHelp, HelpText ) ;
  823.  
  824.  /***************************************************************************
  825.   * Build the display items menu.                        *
  826.   ***************************************************************************/
  827.  
  828.   RebuildDisplayItems ( hwnd, Data ) ;
  829.  
  830.  /***************************************************************************
  831.   * Get the SWAPPATH statement from CONFIG.SYS.                 *
  832.   ***************************************************************************/
  833.  
  834.   Swappath = ScanSystemConfig ( "SWAPPATH" ) ;
  835.  
  836.   if ( Swappath == NULL )
  837.   {
  838.     Swappath = "C:\\OS2\\SYSTEM 0" ;
  839.   }
  840.  
  841.   strupr ( Swappath ) ;
  842.  
  843.   sscanf ( Swappath, "%s %i", Data->SwapPath, &Data->MinFree ) ;
  844.  
  845.  /***************************************************************************
  846.   * Find out where the spool work directory is.                 *
  847.   ***************************************************************************/
  848.  
  849.   Data->SpoolPath = NULL ;
  850.  
  851.   if ( PrfQueryProfileSize ( HINI_PROFILE, "PM_SPOOLER", "DIR", &Size ) )
  852.   {
  853.     Data->SpoolPath = malloc ( (int)Size ) ;
  854.     if ( Data->SpoolPath )
  855.     {
  856.       if ( PrfQueryProfileData ( HINI_PROFILE, "PM_SPOOLER", "DIR", Data->SpoolPath, &Size ) )
  857.       {
  858.     BYTE *p ;
  859.     p = strchr ( Data->SpoolPath, ';' ) ;
  860.     if ( p )
  861.     {
  862.       *p = 0 ;
  863.     }
  864.       }
  865.       else
  866.       {
  867.     free ( Data->SpoolPath ) ;
  868.     Data->SpoolPath = FALSE ;
  869.       }
  870.     }
  871.   }
  872.  
  873.  /***************************************************************************
  874.   * Calibrate the old-style load meter, if the high resolution timer's      *
  875.   *   available.                                *
  876.   ***************************************************************************/
  877.  
  878.   Data->MaxCount = CalibrateLoadMeter ( ) ;
  879.   Data->MaxCount = (ULONG) max ( 1L, Data->MaxCount ) ;
  880.  
  881.  /***************************************************************************
  882.   * Start the new load meter.                            *
  883.   ***************************************************************************/
  884.  
  885.   Data->IdleLoopTID = _beginthread ( CounterThread, NULL, 1024, &Data->IdleCounter ) ;
  886.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, Data->IdleLoopTID ) ;
  887.   DosSuspendThread ( Data->IdleLoopTID ) ;
  888.  
  889.   Data->IdleCount = 0 ;
  890.   Data->IdleCounter = 0 ;
  891.  
  892.   if ( Data->Profile.Items[ITEM_CPULOAD].Flag )
  893.   {
  894.     DosResumeThread ( Data->IdleLoopTID ) ;
  895.   }
  896.  
  897.   MonitorParms = malloc ( sizeof(*MonitorParms) ) ;
  898.   MonitorParms->Counter = & Data->IdleCounter ;
  899.   MonitorParms->Interval = & Data->Profile.TimerInterval ;
  900.   MonitorParms->Owner = hwnd ;
  901.   Data->MonitorLoopTID = _beginthread ( MonitorLoopThread, NULL, 8192, MonitorParms ) ;
  902.  
  903.  /***************************************************************************
  904.   * Add the program to the system task list.                    *
  905.   ***************************************************************************/
  906.  
  907.   WinLoadString ( Data->Anchor, Data->Library, IDS_TITLE, sizeof(Title), Title ) ;
  908.   Add2TaskList ( hwndFrame, Title ) ;
  909.  
  910.  /***************************************************************************
  911.   * Position & size the window.  For some reason, we must move and size     *
  912.   *   the window to the saved position before applying the resizing        *
  913.   *   function as fine-tuning.    Maybe the positioning request fails if        *
  914.   *   the window has no size?                            *
  915.   ***************************************************************************/
  916.  
  917.   WinSetWindowPos ( hwndFrame, HWND_BOTTOM,
  918.     Data->Profile.Position.x, Data->Profile.Position.y,
  919.     Data->Profile.Position.cx, Data->Profile.Position.cy,
  920.     SWP_SIZE | SWP_MOVE | SWP_ZORDER |
  921.     ( Data->Profile.Position.fs & SWP_MINIMIZE ) |
  922.     ( Data->Profile.Position.fs & SWP_RESTORE ) ) ;
  923.  
  924.   ResizeWindow ( hwnd, &Data->Profile ) ;
  925.  
  926.  /***************************************************************************
  927.   * Hide the controls if so configured.                     *
  928.   ***************************************************************************/
  929.  
  930.   if ( Data->Profile.HideControls
  931.     AND NOT ( Data->Profile.Position.fs & SWP_MINIMIZE ) )
  932.   {
  933.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  934.  
  935.     HideControls
  936.     (
  937.       TRUE,
  938.       hwndFrame,
  939.       Data->hwndSysMenu,
  940.       Data->hwndTitleBar,
  941.       Data->hwndMinMax
  942.     ) ;
  943.   }
  944.  
  945.  /***************************************************************************
  946.   * Get the saved presentation parameters and reinstate them.            *
  947.   ***************************************************************************/
  948.  
  949.   if ( Data->Profile.fFontNameSize )
  950.   {
  951.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  952.       strlen(Data->Profile.FontNameSize)+1, Data->Profile.FontNameSize ) ;
  953.   }
  954.  
  955.   if ( Data->Profile.fBackColor )
  956.   {
  957.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  958.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  959.   }
  960.  
  961.   if ( Data->Profile.fTextColor )
  962.   {
  963.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  964.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  965.   }
  966.  
  967.  /***************************************************************************
  968.   * Determine our font size.                            *
  969.   ***************************************************************************/
  970.  
  971.   hPS = WinGetPS ( hwnd ) ;
  972.   WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  973.   WinDrawText ( hPS, 1, " ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  974.   Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  975.   Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  976.   WinReleasePS ( hPS ) ;
  977.  
  978.  /***************************************************************************
  979.   * Now that the window's in order, make it visible.                        *
  980.   ***************************************************************************/
  981.  
  982.   WinShowWindow ( hwndFrame, TRUE ) ;
  983.  
  984.  /***************************************************************************
  985.   * Success?  Return no error.                            *
  986.   ***************************************************************************/
  987.  
  988.   return ( 0 ) ;
  989.  
  990.   hwnd = hwnd ;
  991.   msg = msg ;
  992.   mp1 = mp1 ;
  993.   mp2 = mp2 ;
  994. }
  995.  
  996. /****************************************************************************
  997.  *                                        *
  998.  *    Destroy main window.                            *
  999.  *                                        *
  1000.  ****************************************************************************/
  1001.  
  1002. static MRESULT APIENTRY Destroy
  1003. (
  1004.   HWND hwnd,
  1005.   USHORT msg,
  1006.   MPARAM mp1,
  1007.   MPARAM mp2
  1008. )
  1009. {
  1010.  /***************************************************************************
  1011.   *                Declarations                    *
  1012.   ***************************************************************************/
  1013.  
  1014.   PDATA Data ;
  1015.  
  1016.  /***************************************************************************
  1017.   * Find the instance data.                            *
  1018.   ***************************************************************************/
  1019.  
  1020.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1021.  
  1022.  /***************************************************************************
  1023.   * Release the instance memory.                        *
  1024.   ***************************************************************************/
  1025.  
  1026.   free ( Data ) ;
  1027.  
  1028.  /***************************************************************************
  1029.   * We're done.                                                             *
  1030.   ***************************************************************************/
  1031.  
  1032.   return ( MRFROMSHORT ( 0 ) ) ;
  1033.  
  1034.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1035. }
  1036.  
  1037. /****************************************************************************
  1038.  *                                        *
  1039.  *    Process window resize message.                        *
  1040.  *                                        *
  1041.  ****************************************************************************/
  1042.  
  1043. static MRESULT APIENTRY Size
  1044. (
  1045.   HWND hwnd,
  1046.   USHORT msg,
  1047.   MPARAM mp1,
  1048.   MPARAM mp2
  1049. )
  1050. {
  1051.  /***************************************************************************
  1052.   *                Declarations                    *
  1053.   ***************************************************************************/
  1054.  
  1055.   PDATA Data ;
  1056.  
  1057.   HWND hwndFrame ;
  1058.   SWP Position ;
  1059.  
  1060.  /***************************************************************************
  1061.   * Find the instance data.                            *
  1062.   ***************************************************************************/
  1063.  
  1064.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1065.  
  1066.  /***************************************************************************
  1067.   * Find out the window's new position and size.                            *
  1068.   ***************************************************************************/
  1069.  
  1070.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1071.  
  1072.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1073.  
  1074.   if ( NOT ( Position.fs & SWP_MINIMIZE )
  1075.     AND NOT ( Position.fs & SWP_MAXIMIZE ) )
  1076.   {
  1077.     Data->Profile.Position.x = Position.x ;
  1078.     Data->Profile.Position.y = Position.y ;
  1079.  
  1080.     Data->Profile.Position.cx = Position.cx ;
  1081.     Data->Profile.Position.cy = Position.cy ;
  1082.   }
  1083.  
  1084.  /***************************************************************************
  1085.   * If hiding the controls . . .                        *
  1086.   ***************************************************************************/
  1087.  
  1088.   if ( Data->Profile.HideControls )
  1089.   {
  1090.  
  1091.    /*************************************************************************
  1092.     * If changing to or from minimized state . . .                *
  1093.     *************************************************************************/
  1094.  
  1095.     if ( ( Position.fs & SWP_MINIMIZE ) != ( Data->Profile.Position.fs & SWP_MINIMIZE ) )
  1096.     {
  1097.  
  1098.      /***********************************************************************
  1099.       * Hide the controls if no longer minimized.                *
  1100.       ***********************************************************************/
  1101.  
  1102.       HideControls
  1103.       (
  1104.     NOT ( Position.fs & SWP_MINIMIZE ),
  1105.     hwndFrame,
  1106.     Data->hwndSysMenu,
  1107.     Data->hwndTitleBar,
  1108.     Data->hwndMinMax
  1109.       ) ;
  1110.     }
  1111.   }
  1112.  
  1113.   Data->Profile.Position.fs = Position.fs ;
  1114.  
  1115.  /***************************************************************************
  1116.   * We're done.                                                             *
  1117.   ***************************************************************************/
  1118.  
  1119.   return ( 0 ) ;
  1120.  
  1121.   hwnd = hwnd ;
  1122.   msg = msg ;
  1123.   mp1 = mp1 ;
  1124.   mp2 = mp2 ;
  1125. }
  1126.  
  1127. /****************************************************************************
  1128.  *                                        *
  1129.  *    Process SAVE APPLICATION message.                    *
  1130.  *                                        *
  1131.  ****************************************************************************/
  1132.  
  1133. static MRESULT APIENTRY SaveApplication
  1134. (
  1135.   HWND hwnd,
  1136.   USHORT msg,
  1137.   MPARAM mp1,
  1138.   MPARAM mp2
  1139. )
  1140. {
  1141.  /***************************************************************************
  1142.   *                Declarations                    *
  1143.   ***************************************************************************/
  1144.  
  1145.   PDATA Data ;
  1146.  
  1147.  /***************************************************************************
  1148.   * Find the instance data.                            *
  1149.   ***************************************************************************/
  1150.  
  1151.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1152.  
  1153.  /***************************************************************************
  1154.   * Call function to put all profile data out to the system.            *
  1155.   ***************************************************************************/
  1156.  
  1157.   PutProfile ( &Data->Profile ) ;
  1158.  
  1159.  /***************************************************************************
  1160.   * We're done.  Let the system complete default processing.                *
  1161.   ***************************************************************************/
  1162.  
  1163.   return ( WinDefWindowProc ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ) ;
  1164.  
  1165.   hwnd = hwnd ;
  1166.   msg = msg ;
  1167.   mp1 = mp1 ;
  1168.   mp2 = mp2 ;
  1169. }
  1170.  
  1171. /****************************************************************************
  1172.  *                                        *
  1173.  *    Repaint entire window.                            *
  1174.  *                                        *
  1175.  ****************************************************************************/
  1176.  
  1177. static MRESULT APIENTRY Paint
  1178. (
  1179.   HWND hwnd,
  1180.   USHORT msg,
  1181.   MPARAM mp1,
  1182.   MPARAM mp2
  1183. )
  1184. {
  1185.  /***************************************************************************
  1186.   *                Declarations                    *
  1187.   ***************************************************************************/
  1188.  
  1189.   PDATA Data ;
  1190.   HPS hPS ;
  1191.   RECTL Rectangle ;
  1192.  
  1193.  /***************************************************************************
  1194.   * Find the instance data.                            *
  1195.   ***************************************************************************/
  1196.  
  1197.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1198.  
  1199.  /***************************************************************************
  1200.   * Get presentation space and make it use RGB colors.                *
  1201.   ***************************************************************************/
  1202.  
  1203.   hPS = WinBeginPaint ( hwnd, NULL, NULL ) ;
  1204.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  1205.  
  1206.  /***************************************************************************
  1207.   * Clear the window.                                *
  1208.   ***************************************************************************/
  1209.  
  1210.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  1211.  
  1212.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  1213.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  1214.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  1215.  
  1216.  /***************************************************************************
  1217.   * Release presentation space.                         *
  1218.   ***************************************************************************/
  1219.  
  1220.   WinEndPaint ( hPS ) ;
  1221.  
  1222.  /***************************************************************************
  1223.   * Update the window and return.                        *
  1224.   ***************************************************************************/
  1225.  
  1226.   UpdateWindow ( hwnd, Data, TRUE ) ;
  1227.  
  1228.   return ( 0 ) ;
  1229.  
  1230.   hwnd = hwnd ;
  1231.   msg = msg ;
  1232.   mp1 = mp1 ;
  1233.   mp2 = mp2 ;
  1234. }
  1235.  
  1236. /****************************************************************************
  1237.  *                                        *
  1238.  *    Process commands received by Main Window                *
  1239.  *                                        *
  1240.  ****************************************************************************/
  1241.  
  1242. static MRESULT APIENTRY Command
  1243. (
  1244.   HWND hwnd,
  1245.   USHORT msg,
  1246.   MPARAM mp1,
  1247.   MPARAM mp2
  1248. )
  1249. {
  1250.  /***************************************************************************
  1251.   * Local Declarations                                *
  1252.   ***************************************************************************/
  1253.  
  1254.   static METHOD Methods [] =
  1255.   {
  1256.     { IDM_SAVE_APPLICATION, SaveApplication },
  1257.     { IDM_RESET_DEFAULTS,   ResetDefaults   },
  1258.     { IDM_HIDE_CONTROLS,    HideControlsCmd },
  1259.     { IDM_SET_TIMER,        SetTimer        },
  1260.     { IDM_EXIT,         Exit        },
  1261.     { IDM_ABOUT,        About        },
  1262.   } ;
  1263.  
  1264.   USHORT Command ;
  1265.   PDATA Data ;
  1266.   short i ;
  1267.  
  1268.  /***************************************************************************
  1269.   * Find the instance data.                            *
  1270.   ***************************************************************************/
  1271.  
  1272.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1273.  
  1274.  /***************************************************************************
  1275.   * Process indicated command . . .                        *
  1276.   ***************************************************************************/
  1277.  
  1278.   Command = SHORT1FROMMP ( mp1 ) ;
  1279.  
  1280.  /***************************************************************************
  1281.   * Process display item commands.                        *
  1282.   ***************************************************************************/
  1283.  
  1284.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  1285.   {
  1286.     PITEM Item = & Data->Profile.Items [i] ;
  1287.  
  1288.     if ( Command == Item->MenuId )
  1289.     {
  1290.       HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1291.  
  1292.       Item->Flag = Item->Flag ? FALSE : TRUE ;
  1293.  
  1294.       if ( i == ITEM_CPULOAD )
  1295.       {
  1296.     if ( Item->Flag )
  1297.       DosResumeThread ( Data->IdleLoopTID ) ;
  1298.     else
  1299.       DosSuspendThread ( Data->IdleLoopTID ) ;
  1300.       }
  1301.  
  1302.       CheckMenuItem ( hwndFrame, FID_SYSMENU, Item->MenuId, Item->Flag ) ;
  1303.  
  1304.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1305.  
  1306.       return ( MRFROMSHORT ( 0 ) ) ;
  1307.     }
  1308.   }
  1309.  
  1310.  /***************************************************************************
  1311.   * Dispatch all other commands through the method table.            *
  1312.   ***************************************************************************/
  1313.  
  1314.   return ( DispatchMessage ( hwnd, SHORT1FROMMP(mp1), mp1, mp2, Methods, sizeof(Methods)/sizeof(Methods[0]), NULL ) ) ;
  1315.  
  1316.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1317. }
  1318.  
  1319. /****************************************************************************
  1320.  *                                        *
  1321.  *    Process Reset Defaults menu command.                    *
  1322.  *                                        *
  1323.  ****************************************************************************/
  1324.  
  1325. static MRESULT APIENTRY ResetDefaults
  1326.   HWND hwnd, 
  1327.   USHORT msg, 
  1328.   MPARAM mp1, 
  1329.   MPARAM mp2
  1330. )
  1331. {
  1332.  /***************************************************************************
  1333.   * Reset all profile data for this program.                    *
  1334.   ***************************************************************************/
  1335.  
  1336.   PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, NULL, NULL, 0 ) ;
  1337.  
  1338.  /***************************************************************************
  1339.   * Reset the program's presentation parameters.                            *
  1340.   ***************************************************************************/
  1341.  
  1342.   WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  1343.   WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  1344.   WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  1345.  
  1346.  /***************************************************************************
  1347.   * Done.                                    *
  1348.   ***************************************************************************/
  1349.  
  1350.   return ( MRFROMSHORT ( 0 ) ) ;
  1351.  
  1352.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1353. }
  1354.  
  1355. /****************************************************************************
  1356.  *                                        *
  1357.  *    Process Hide Controls menu command.                    *
  1358.  *                                        *
  1359.  ****************************************************************************/
  1360.  
  1361. static MRESULT APIENTRY HideControlsCmd
  1362.   HWND hwnd, 
  1363.   USHORT msg, 
  1364.   MPARAM mp1, 
  1365.   MPARAM mp2
  1366. )
  1367. {
  1368.  /***************************************************************************
  1369.   * Local Declarations.                             *
  1370.   ***************************************************************************/
  1371.  
  1372.   PDATA Data ;
  1373.   HWND hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1374.  
  1375.  /***************************************************************************
  1376.   * Find the instance data.                            *
  1377.   ***************************************************************************/
  1378.  
  1379.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1380.  
  1381.  /***************************************************************************
  1382.   * Toggle the Hide Controls setting.                        *
  1383.   ***************************************************************************/
  1384.  
  1385.   Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  1386.   Data->Profile.fHideControls = TRUE ;
  1387.  
  1388.  /***************************************************************************
  1389.   * If controls aren't hidden yet, update the menu check-mark.              *
  1390.   ***************************************************************************/
  1391.  
  1392.   if ( Data->Profile.HideControls )
  1393.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1394.  
  1395.  /***************************************************************************
  1396.   * If not minimized right now, hide or reveal the controls.            *
  1397.   ***************************************************************************/
  1398.  
  1399.   if ( NOT ( Data->Profile.Position.fs & SWP_MINIMIZE ) )
  1400.   {
  1401.     HideControls
  1402.     (
  1403.       Data->Profile.HideControls,
  1404.       hwndFrame,
  1405.       Data->hwndSysMenu,
  1406.       Data->hwndTitleBar,
  1407.       Data->hwndMinMax
  1408.     ) ;
  1409.   }
  1410.  
  1411.  /***************************************************************************
  1412.   * If controls are no longer hidden, update the menu check-mark.        *
  1413.   ***************************************************************************/
  1414.  
  1415.   if ( NOT Data->Profile.HideControls )
  1416.     CheckMenuItem ( hwndFrame, FID_SYSMENU, IDM_HIDE_CONTROLS, Data->Profile.HideControls ) ;
  1417.  
  1418.  /***************************************************************************
  1419.   * Done.                                    *
  1420.   ***************************************************************************/
  1421.  
  1422.   return ( MRFROMSHORT ( 0 ) ) ;
  1423.  
  1424.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1425. }
  1426.  
  1427. /****************************************************************************
  1428.  *                                        *
  1429.  *    Process Set Timer menu command.                     *
  1430.  *                                        *
  1431.  ****************************************************************************/
  1432.  
  1433. static MRESULT APIENTRY SetTimer
  1434.   HWND hwnd, 
  1435.   USHORT msg, 
  1436.   MPARAM mp1, 
  1437.   MPARAM mp2
  1438. )
  1439. {
  1440.  /***************************************************************************
  1441.   * Local Declarations.                             *
  1442.   ***************************************************************************/
  1443.  
  1444.   PDATA Data ;
  1445.   SETTIMER_PARMS Parms ;
  1446.  
  1447.  /***************************************************************************
  1448.   * Find the instance data.                            *
  1449.   ***************************************************************************/
  1450.  
  1451.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1452.  
  1453.  /***************************************************************************
  1454.   * Invoke the Set Timer dialog.                        *
  1455.   ***************************************************************************/
  1456.  
  1457.   Parms.id = IDD_SET_TIMER ;
  1458.   Parms.hwndHelp = WinQueryHelpInstance ( hwnd ) ;
  1459.   Parms.TimerInterval = & Data->Profile.TimerInterval ;
  1460.  
  1461.   WinDlgBox ( HWND_DESKTOP, hwnd, SetTimerProcessor,
  1462.     Data->Library, IDD_SET_TIMER, &Parms ) ;
  1463.  
  1464.  /***************************************************************************
  1465.   * Done.                                    *
  1466.   ***************************************************************************/
  1467.  
  1468.   return ( MRFROMSHORT ( 0 ) ) ;
  1469.  
  1470.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1471. }
  1472.  
  1473. /****************************************************************************
  1474.  *                                        *
  1475.  *    Process About menu command.                        *
  1476.  *                                        *
  1477.  ****************************************************************************/
  1478.  
  1479. static MRESULT APIENTRY About
  1480.   HWND hwnd, 
  1481.   USHORT msg, 
  1482.   MPARAM mp1, 
  1483.   MPARAM mp2
  1484. )
  1485. {
  1486.  /***************************************************************************
  1487.   * Local Declarations                                *
  1488.   ***************************************************************************/
  1489.  
  1490.   PDATA Data ;
  1491.   ABOUT_PARMS Parms ;
  1492.  
  1493.  /***************************************************************************
  1494.   * Find the instance data.                            *
  1495.   ***************************************************************************/
  1496.  
  1497.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1498.  
  1499.  /***************************************************************************
  1500.   * Invoke the About dialog.                            *
  1501.   ***************************************************************************/
  1502.  
  1503.   Parms.id = IDD_ABOUT ;
  1504.   Parms.hwndHelp = WinQueryHelpInstance ( hwnd ) ;
  1505.  
  1506.   WinDlgBox ( HWND_DESKTOP, hwnd, AboutProcessor,
  1507.     Data->Library, IDD_ABOUT, &Parms ) ;
  1508.  
  1509.  /***************************************************************************
  1510.   * Done.                                    *
  1511.   ***************************************************************************/
  1512.  
  1513.   return ( MRFROMSHORT ( 0 ) ) ;
  1514.  
  1515.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1516. }
  1517.  
  1518. /****************************************************************************
  1519.  *                                        *
  1520.  *    Process Mouse Button being pressed.                    *
  1521.  *                                        *
  1522.  ****************************************************************************/
  1523.  
  1524. static MRESULT APIENTRY ButtonDown
  1525. (
  1526.   HWND hwnd,
  1527.   USHORT msg,
  1528.   MPARAM mp1,
  1529.   MPARAM mp2
  1530. )
  1531. {
  1532.  /***************************************************************************
  1533.   * Local Declarations                                *
  1534.   ***************************************************************************/
  1535.  
  1536.   PDATA Data ;
  1537.   HWND hwndFrame ;
  1538.   SWP Position ;
  1539.   TRACKINFO TrackInfo ;
  1540.  
  1541.  /***************************************************************************
  1542.   * Find the instance data.                            *
  1543.   ***************************************************************************/
  1544.  
  1545.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1546.  
  1547.  /***************************************************************************
  1548.   * Determine the new window position.                        *
  1549.   ***************************************************************************/
  1550.  
  1551.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  1552.  
  1553.   TrackInfo.cxBorder = 1 ;
  1554.   TrackInfo.cyBorder = 1 ;
  1555.   TrackInfo.cxGrid = 1 ;
  1556.   TrackInfo.cyGrid = 1 ;
  1557.   TrackInfo.cxKeyboard = 8 ;
  1558.   TrackInfo.cyKeyboard = 8 ;
  1559.  
  1560.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1561.  
  1562.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1563.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1564.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1565.   TrackInfo.rclTrack.yBottom = Position.y ;
  1566.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1567.  
  1568.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1569.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1570.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1571.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1572.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1573.  
  1574.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1575.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1576.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1577.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1578.  
  1579.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1580.  
  1581.   if ( WinTrackRect ( HWND_DESKTOP, NULL, &TrackInfo ) )
  1582.   {
  1583.     WinSetWindowPos ( hwndFrame, NULL,
  1584.       (SHORT) TrackInfo.rclTrack.xLeft,
  1585.       (SHORT) TrackInfo.rclTrack.yBottom,
  1586.       0, 0, SWP_MOVE ) ;
  1587.   }
  1588.  
  1589.  /***************************************************************************
  1590.   * Return through the default processor, letting window activation        *
  1591.   *   and other system functions occur.                     *
  1592.   ***************************************************************************/
  1593.  
  1594.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1595.  
  1596.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1597. }
  1598.  
  1599. /****************************************************************************
  1600.  *                                        *
  1601.  *    Process Mouse Button having been double-clicked.            *
  1602.  *                                        *
  1603.  ****************************************************************************/
  1604.  
  1605. static MRESULT APIENTRY ButtonDblClick
  1606. (
  1607.   HWND hwnd,
  1608.   USHORT msg,
  1609.   MPARAM mp1,
  1610.   MPARAM mp2
  1611. )
  1612. {
  1613.  /***************************************************************************
  1614.   * Send message to self to stop hiding the controls.                *
  1615.   ***************************************************************************/
  1616.  
  1617.   WinPostMsg ( hwnd, WM_COMMAND,
  1618.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1619.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1620.  
  1621.  /***************************************************************************
  1622.   * Return through the default processor, letting window activation        *
  1623.   *   and other system functions occur.                     *
  1624.   ***************************************************************************/
  1625.  
  1626.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1627.  
  1628.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1629. }
  1630.  
  1631. /****************************************************************************
  1632.  *                                        *
  1633.  *    Process Presentation Parameter Changed notification.            *
  1634.  *                                        *
  1635.  ****************************************************************************/
  1636.  
  1637. static MRESULT APIENTRY PresParamChanged
  1638. (
  1639.   HWND hwnd,
  1640.   USHORT msg,
  1641.   MPARAM mp1,
  1642.   MPARAM mp2
  1643. )
  1644. {
  1645.  /***************************************************************************
  1646.   * Local Declarations                                *
  1647.   ***************************************************************************/
  1648.  
  1649.   PDATA Data ;
  1650.   HPS hPS ;
  1651.   ULONG ppid ;
  1652.   RECTL Rectangle ;
  1653.  
  1654.  /***************************************************************************
  1655.   * Find the instance data.                            *
  1656.   ***************************************************************************/
  1657.  
  1658.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1659.  
  1660.  /***************************************************************************
  1661.   * Get the presentation parameter that changed.                *
  1662.   ***************************************************************************/
  1663.  
  1664.   switch ( LONGFROMMP(mp1) )
  1665.   {
  1666.  
  1667.    /*************************************************************************
  1668.     * If font, note the fact that we now have a font to be saved as        *
  1669.     *    part of the configuration.  Get the font metrics and resize        *
  1670.     *    the window appropriately.                        *
  1671.     *************************************************************************/
  1672.  
  1673.     case PP_FONTNAMESIZE:
  1674.     {
  1675.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1676.     sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1677.     0 ) )
  1678.       {
  1679.     Data->Profile.fFontNameSize = TRUE ;
  1680.       }
  1681.       else
  1682.       {
  1683.     strcpy ( Data->Profile.FontNameSize, "" ) ;
  1684.     Data->Profile.fFontNameSize = FALSE ;
  1685.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "FontNameSize", NULL, 0 ) ;
  1686.       }
  1687.  
  1688.       hPS = WinGetPS ( hwnd ) ;
  1689.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1690.       WinDrawText ( hPS, 1, " ", &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1691.       Data->Width  = Rectangle.xRight - Rectangle.xLeft ;
  1692.       Data->Height = Rectangle.yTop - Rectangle.yBottom ;
  1693.       WinReleasePS ( hPS ) ;
  1694.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1695.       break ;
  1696.     }
  1697.  
  1698.    /*************************************************************************
  1699.     * If background color, note the fact and repaint the window.        *
  1700.     *************************************************************************/
  1701.  
  1702.     case PP_BACKGROUNDCOLOR:
  1703.     {
  1704.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1705.     sizeof(Data->Profile.BackColor), &Data->Profile.BackColor, 0 ) )
  1706.       {
  1707.     Data->Profile.fBackColor = TRUE ;
  1708.       }
  1709.       else
  1710.       {
  1711.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1712.     Data->Profile.fBackColor = FALSE ;
  1713.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "BackgroundColor", NULL, 0 ) ;
  1714.       }
  1715.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1716.       break ;
  1717.     }
  1718.  
  1719.    /*************************************************************************
  1720.     * If foreground color, note the fact and repaint the window.        *
  1721.     *************************************************************************/
  1722.  
  1723.     case PP_FOREGROUNDCOLOR:
  1724.     {
  1725.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1726.     sizeof(Data->Profile.TextColor), &Data->Profile.TextColor, 0 ) )
  1727.       {
  1728.     Data->Profile.fTextColor = TRUE ;
  1729.       }
  1730.       else
  1731.       {
  1732.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1733.     Data->Profile.fTextColor = FALSE ;
  1734.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "ForegroundColor", NULL, 0 ) ;
  1735.       }
  1736.       WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1737.       break ;
  1738.     }
  1739.   }
  1740.  
  1741.  /***************************************************************************
  1742.   * Return through the default processor, letting window activation        *
  1743.   *   and other system functions occur.                     *
  1744.   ***************************************************************************/
  1745.  
  1746.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1747.  
  1748.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1749. }
  1750.  
  1751. /****************************************************************************
  1752.  *                                        *
  1753.  *    Process System Color Change notification.                *
  1754.  *                                        *
  1755.  ****************************************************************************/
  1756.  
  1757. static MRESULT APIENTRY SysColorChange
  1758. (
  1759.   HWND hwnd,
  1760.   USHORT msg,
  1761.   MPARAM mp1,
  1762.   MPARAM mp2
  1763. )
  1764. {
  1765.  /***************************************************************************
  1766.   * Local Declarations                                *
  1767.   ***************************************************************************/
  1768.  
  1769.   PDATA Data ;
  1770.  
  1771.  /***************************************************************************
  1772.   * Find the instance data.                            *
  1773.   ***************************************************************************/
  1774.  
  1775.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1776.  
  1777.  /***************************************************************************
  1778.   * If we aren't using custom colors, then query for the new defaults.      *
  1779.   ***************************************************************************/
  1780.  
  1781.   if ( NOT Data->Profile.fBackColor )
  1782.   {
  1783.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1784.   }
  1785.  
  1786.   if ( NOT Data->Profile.fTextColor )
  1787.   {
  1788.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1789.   }
  1790.  
  1791.  /***************************************************************************
  1792.   * Return value must be NULL, according to the documentation.            *
  1793.   ***************************************************************************/
  1794.  
  1795.   return ( MRFROMP ( NULL ) ) ;
  1796.  
  1797.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1798. }
  1799.  
  1800. /****************************************************************************
  1801.  *                                        *
  1802.  *    Process Query for Keys Help resource id.                *
  1803.  *                                        *
  1804.  ****************************************************************************/
  1805.  
  1806. static MRESULT APIENTRY QueryKeysHelp
  1807. (
  1808.   HWND hwnd,
  1809.   USHORT msg,
  1810.   MPARAM mp1,
  1811.   MPARAM mp2
  1812. )
  1813. {
  1814.  /***************************************************************************
  1815.   * Simply return the ID of the Keys Help panel.                *
  1816.   ***************************************************************************/
  1817.  
  1818.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1819.  
  1820.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1821. }
  1822.  
  1823. /****************************************************************************
  1824.  *                                        *
  1825.  *    Process Help Manager Error                        *
  1826.  *                                        *
  1827.  ****************************************************************************/
  1828.  
  1829. static MRESULT APIENTRY HelpError
  1830.   HWND hwnd, 
  1831.   USHORT msg, 
  1832.   MPARAM mp1, 
  1833.   MPARAM mp2
  1834. )
  1835. {
  1836.  /***************************************************************************
  1837.   * Local Declarations                                *
  1838.   ***************************************************************************/
  1839.  
  1840.   static struct
  1841.   {
  1842.     ULONG Error ;
  1843.     USHORT StringId ;
  1844.   }
  1845.   HelpErrors [] =
  1846.   {
  1847.     { HMERR_NO_FRAME_WND_IN_CHAIN,     IDS_HMERR_NO_FRAME_WND_IN_CHAIN },
  1848.     { HMERR_INVALID_ASSOC_APP_WND,     IDS_HMERR_INVALID_ASSOC_APP_WND },
  1849.     { HMERR_INVALID_ASSOC_HELP_INST,   IDS_HMERR_INVALID_ASSOC_HELP_IN },
  1850.     { HMERR_INVALID_DESTROY_HELP_INST, IDS_HMERR_INVALID_DESTROY_HELP_ },
  1851.     { HMERR_NO_HELP_INST_IN_CHAIN,     IDS_HMERR_NO_HELP_INST_IN_CHAIN },
  1852.     { HMERR_INVALID_HELP_INSTANCE_HDL, IDS_HMERR_INVALID_HELP_INSTANCE },
  1853.     { HMERR_INVALID_QUERY_APP_WND,     IDS_HMERR_INVALID_QUERY_APP_WND },
  1854.     { HMERR_HELP_INST_CALLED_INVALID,  IDS_HMERR_HELP_INST_CALLED_INVA },
  1855.     { HMERR_HELPTABLE_UNDEFINE,        IDS_HMERR_HELPTABLE_UNDEFINE    },
  1856.     { HMERR_HELP_INSTANCE_UNDEFINE,    IDS_HMERR_HELP_INSTANCE_UNDEFIN },
  1857.     { HMERR_HELPITEM_NOT_FOUND,        IDS_HMERR_HELPITEM_NOT_FOUND    },
  1858.     { HMERR_INVALID_HELPSUBITEM_SIZE,  IDS_HMERR_INVALID_HELPSUBITEM_S },
  1859.     { HMERR_HELPSUBITEM_NOT_FOUND,     IDS_HMERR_HELPSUBITEM_NOT_FOUND },
  1860.     { HMERR_INDEX_NOT_FOUND,           IDS_HMERR_INDEX_NOT_FOUND       },
  1861.     { HMERR_CONTENT_NOT_FOUND,           IDS_HMERR_CONTENT_NOT_FOUND     },
  1862.     { HMERR_OPEN_LIB_FILE,           IDS_HMERR_OPEN_LIB_FILE           },
  1863.     { HMERR_READ_LIB_FILE,           IDS_HMERR_READ_LIB_FILE           },
  1864.     { HMERR_CLOSE_LIB_FILE,           IDS_HMERR_CLOSE_LIB_FILE        },
  1865.     { HMERR_INVALID_LIB_FILE,           IDS_HMERR_INVALID_LIB_FILE      },
  1866.     { HMERR_NO_MEMORY,               IDS_HMERR_NO_MEMORY           },
  1867.     { HMERR_ALLOCATE_SEGMENT,           IDS_HMERR_ALLOCATE_SEGMENT      },
  1868.     { HMERR_FREE_MEMORY,           IDS_HMERR_FREE_MEMORY           },
  1869.     { HMERR_PANEL_NOT_FOUND,           IDS_HMERR_PANEL_NOT_FOUND       },
  1870.     { HMERR_DATABASE_NOT_OPEN,           IDS_HMERR_DATABASE_NOT_OPEN     },
  1871.     { 0,                   IDS_HMERR_UNKNOWN           }
  1872.   } ;
  1873.  
  1874.   PDATA Data ;
  1875.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1876.   int Index ;
  1877.   char Message [200] ;
  1878.   char Title [80] ;
  1879.  
  1880.  /***************************************************************************
  1881.   * Find the instance data.                            *
  1882.   ***************************************************************************/
  1883.  
  1884.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1885.  
  1886.  /***************************************************************************
  1887.   * Find the error code in the message table.                    *
  1888.   ***************************************************************************/
  1889.  
  1890.   Index = 0 ;
  1891.   while ( HelpErrors[Index].Error
  1892.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1893.   {
  1894.     Index ++ ;
  1895.   }
  1896.  
  1897.  /***************************************************************************
  1898.   * Get the message texts.                            *
  1899.   ***************************************************************************/
  1900.  
  1901.   WinLoadString ( Data->Anchor, Data->Library, IDS_HMERR, sizeof(Title), Title ) ;
  1902.  
  1903.   WinLoadString ( Data->Anchor, Data->Library, HelpErrors[Index].StringId, sizeof(Message), Message ) ;
  1904.  
  1905.  /***************************************************************************
  1906.   * Display the error message.                            *
  1907.   ***************************************************************************/
  1908.  
  1909.   WinMessageBox
  1910.   (
  1911.     HWND_DESKTOP,
  1912.     hwnd,
  1913.     Message,
  1914.     Title,
  1915.     0,
  1916.     MB_OK | MB_WARNING
  1917.   ) ;
  1918.  
  1919.  /***************************************************************************
  1920.   * Return zero, indicating that the message was processed.            *
  1921.   ***************************************************************************/
  1922.  
  1923.   return ( MRFROMSHORT ( 0 ) ) ;
  1924.  
  1925.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1926. }
  1927.  
  1928. /****************************************************************************
  1929.  *                                        *
  1930.  *    Process "Extended Help Undefined" notification                *
  1931.  *                                        *
  1932.  ****************************************************************************/
  1933.  
  1934. static MRESULT APIENTRY ExtHelpUndefined
  1935.   HWND hwnd, 
  1936.   USHORT msg, 
  1937.   MPARAM mp1, 
  1938.   MPARAM mp2
  1939. )
  1940. {
  1941.  /***************************************************************************
  1942.   * Local Declarations                                *
  1943.   ***************************************************************************/
  1944.  
  1945.   PDATA Data ;
  1946.   char Message [200] ;
  1947.   char Title [80] ;
  1948.  
  1949.  /***************************************************************************
  1950.   * Find the instance data.                            *
  1951.   ***************************************************************************/
  1952.  
  1953.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  1954.  
  1955.  /***************************************************************************
  1956.   * Get the message texts.                            *
  1957.   ***************************************************************************/
  1958.  
  1959.   WinLoadString ( Data->Anchor, Data->Library, IDS_HMERR, sizeof(Title), Title ) ;
  1960.  
  1961.   WinLoadString ( Data->Anchor, Data->Library, IDS_HMERR_EXTHELPUNDEFINED, sizeof(Message), Message ) ;
  1962.  
  1963.  /***************************************************************************
  1964.   * Display the error message.                            *
  1965.   ***************************************************************************/
  1966.  
  1967.   WinMessageBox
  1968.   (
  1969.     HWND_DESKTOP,
  1970.     hwnd,
  1971.     Message,
  1972.     Title,
  1973.     0,
  1974.     MB_OK | MB_WARNING
  1975.   ) ;
  1976.  
  1977.  /***************************************************************************
  1978.   * Return zero, indicating that the message was processed.            *
  1979.   ***************************************************************************/
  1980.  
  1981.   return ( MRFROMSHORT ( 0 ) ) ;
  1982.  
  1983.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  1984. }
  1985.  
  1986. /****************************************************************************
  1987.  *                                        *
  1988.  *    Process "Help Subitem Not Found" notification                *
  1989.  *                                        *
  1990.  ****************************************************************************/
  1991.  
  1992. static MRESULT APIENTRY HelpSubitemNotFound
  1993.   HWND hwnd, 
  1994.   USHORT msg, 
  1995.   MPARAM mp1, 
  1996.   MPARAM mp2
  1997. )
  1998. {
  1999.  /***************************************************************************
  2000.   * Local Declarations                                *
  2001.   ***************************************************************************/
  2002.  
  2003.   PDATA Data ;
  2004.   int i ;
  2005.   BYTE Format [200] ;
  2006.   BYTE Message [200] ;
  2007.   BYTE Mode [40] ;
  2008.   USHORT Subtopic ;
  2009.   char Title [80] ;
  2010.   USHORT Topic ;
  2011.  
  2012.  /***************************************************************************
  2013.   * Find the instance data.                            *
  2014.   ***************************************************************************/
  2015.  
  2016.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  2017.  
  2018.  /***************************************************************************
  2019.   * Get the title text.                             *
  2020.   ***************************************************************************/
  2021.  
  2022.   WinLoadString ( Data->Anchor, Data->Library, IDS_HMERR, sizeof(Title), Title ) ;
  2023.  
  2024.  /***************************************************************************
  2025.   * Format the error message.                            *
  2026.   ***************************************************************************/
  2027.  
  2028.   Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  2029.   Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  2030.  
  2031.   i = SHORT1FROMMP ( mp1 ) ;
  2032.  
  2033.   switch ( i )
  2034.   {
  2035.     case HLPM_FRAME:
  2036.       WinLoadString ( Data->Anchor, Data->Library, IDS_HELPMODE_FRAME, sizeof(Mode), Mode ) ;
  2037.       break ;
  2038.  
  2039.     case HLPM_MENU:
  2040.       WinLoadString ( Data->Anchor, Data->Library, IDS_HELPMODE_MENU, sizeof(Mode), Mode ) ;
  2041.       break ;
  2042.  
  2043.     case HLPM_WINDOW:
  2044.       WinLoadString ( Data->Anchor, Data->Library, IDS_HELPMODE_WINDOW, sizeof(Mode), Mode ) ;
  2045.       break ;
  2046.  
  2047.     default:
  2048.       WinLoadString ( Data->Anchor, Data->Library, IDS_HELPMODE_UNKNOWN, sizeof(Mode), Mode ) ;
  2049.   }
  2050.  
  2051.   WinLoadString ( Data->Anchor, Data->Library, IDS_HELPSUBITEMNOTFOUND, sizeof(Format), Format ) ;
  2052.  
  2053.   sprintf ( Message, Format, Mode, Topic, Subtopic ) ;
  2054.  
  2055.  /***************************************************************************
  2056.   * Display the error message.                            *
  2057.   ***************************************************************************/
  2058.  
  2059.   WinMessageBox
  2060.   (
  2061.     HWND_DESKTOP,
  2062.     hwnd,
  2063.     Message,
  2064.     Title,
  2065.     0,
  2066.     MB_OK | MB_WARNING
  2067.   ) ;
  2068.  
  2069.  /***************************************************************************
  2070.   * Return zero, indicating that the message was processed.            *
  2071.   ***************************************************************************/
  2072.  
  2073.   return ( MRFROMSHORT ( 0 ) ) ;
  2074.  
  2075.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  2076. }
  2077.  
  2078. /****************************************************************************
  2079.  *                                        *
  2080.  *    Process Refresh message.                        *
  2081.  *                                        *
  2082.  ****************************************************************************/
  2083.  
  2084. static MRESULT APIENTRY Refresh
  2085.   HWND hwnd, 
  2086.   USHORT msg, 
  2087.   MPARAM mp1, 
  2088.   MPARAM mp2
  2089. )
  2090. {
  2091.  /***************************************************************************
  2092.   * Local Declarations                                *
  2093.   ***************************************************************************/
  2094.  
  2095.   PDATA Data ;
  2096.   USHORT Drive ;
  2097.   ULONG Drives ;
  2098.  
  2099.  /***************************************************************************
  2100.   * Find the instance data.                            *
  2101.   ***************************************************************************/
  2102.  
  2103.   Data = (PDATA) WinQueryWindowPtr ( hwnd, QWL_USER ) ;
  2104.  
  2105.  /***************************************************************************
  2106.   * Save the idle counter.                            *
  2107.   ***************************************************************************/
  2108.  
  2109.   Data->IdleCount = LONGFROMMP ( mp1 ) ;
  2110.  
  2111.  /***************************************************************************
  2112.   * Determine if drive mask has changed.                    *
  2113.   ***************************************************************************/
  2114.  
  2115.   DosQCurDisk ( &Drive, &Drives ) ;
  2116.  
  2117.   if ( Drives != Data->Drives )
  2118.   {
  2119.    /*************************************************************************
  2120.     * It has.  First save the display options.                    *
  2121.     *************************************************************************/
  2122.  
  2123.     SaveApplication ( hwnd, WM_SAVEAPPLICATION, 0, 0 ) ;
  2124.  
  2125.    /*************************************************************************
  2126.     * Next, update the drive item list.                     *
  2127.     *************************************************************************/
  2128.  
  2129.     UpdateDriveList ( Data->Anchor, Data->Library, &Data->Profile, Data->Drives ) ;
  2130.  
  2131.    /*************************************************************************
  2132.     * If the controls are hidden, hide the whole window and reveal the        *
  2133.     *    controls.  Otherwise the menu wouldn't get updated correctly.       *
  2134.     *************************************************************************/
  2135.  
  2136.     if ( Data->Profile.HideControls )
  2137.     {
  2138.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT,FALSE), FALSE ) ;
  2139.       HideControls
  2140.       (
  2141.     FALSE,
  2142.     WinQueryWindow ( hwnd, QW_PARENT, FALSE ),
  2143.     Data->hwndSysMenu,
  2144.     Data->hwndTitleBar,
  2145.     Data->hwndMinMax
  2146.       ) ;
  2147.     }
  2148.  
  2149.    /*************************************************************************
  2150.     * Update the menu.                                *
  2151.     *************************************************************************/
  2152.  
  2153.     RebuildDisplayItems ( hwnd, Data ) ;
  2154.  
  2155.    /*************************************************************************
  2156.     * If the controls were supposed to be hidden, hide them once more and   *
  2157.     *    show the window to the world again.                    *
  2158.     *************************************************************************/
  2159.  
  2160.     if ( Data->Profile.HideControls )
  2161.     {
  2162.       HideControls
  2163.       (
  2164.     TRUE,
  2165.     WinQueryWindow ( hwnd, QW_PARENT, FALSE ),
  2166.     Data->hwndSysMenu,
  2167.     Data->hwndTitleBar,
  2168.     Data->hwndMinMax
  2169.       ) ;
  2170.       WinShowWindow ( WinQueryWindow(hwnd,QW_PARENT,FALSE), TRUE ) ;
  2171.     }
  2172.  
  2173.    /*************************************************************************
  2174.     * Save the updated drive mask.                        *
  2175.     *************************************************************************/
  2176.  
  2177.     Data->Drives = Drives ;
  2178.  
  2179.    /*************************************************************************
  2180.     * Resize the window to accommodate the new option list.            *
  2181.     *************************************************************************/
  2182.  
  2183.     ResizeWindow ( hwnd, &Data->Profile ) ;
  2184.   }
  2185.  
  2186.  /***************************************************************************
  2187.   * Update the statistics.                            *
  2188.   ***************************************************************************/
  2189.  
  2190.   UpdateWindow ( hwnd, Data, FALSE ) ;
  2191.  
  2192.  /***************************************************************************
  2193.   * Return zero, indicating that the message was processed.            *
  2194.   ***************************************************************************/
  2195.  
  2196.   return ( MRFROMSHORT ( 0 ) ) ;
  2197.  
  2198.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;
  2199. }
  2200.  
  2201.  
  2202. /****************************************************************************
  2203.  *                                        *
  2204.  *                 Get Profile Data                    *
  2205.  *                                        *
  2206.  ****************************************************************************/
  2207.  
  2208. static void GetProfile ( HAB Anchor, HMODULE Library, PPROFILE Profile )
  2209. {
  2210.  /***************************************************************************
  2211.   * Local Declarations                                *
  2212.   ***************************************************************************/
  2213.  
  2214.   int i ;
  2215.   ULONG Size ;
  2216.  
  2217.  /***************************************************************************
  2218.   * Build the fixed portion of the item list.                    *
  2219.   ***************************************************************************/
  2220.  
  2221.   for ( i=0; i<ITEM_BASE_COUNT; i++ )
  2222.   {
  2223.     WinLoadString ( Anchor, Library, i*2+IDS_SHOW_CLOCK_LABEL,
  2224.       sizeof(Items[i].Label), Items[i].Label ) ;
  2225.  
  2226.     WinLoadString ( Anchor, Library, i*2+IDS_SHOW_CLOCK_OPTION,
  2227.       sizeof(Items[i].MenuOption), Items[i].MenuOption ) ;
  2228.  
  2229.     Items[i].Flag = TRUE ;
  2230.     if
  2231.     (
  2232.       PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, Items[i].Name, &Size )
  2233.       AND
  2234.       ( Size == sizeof(Items[i].Flag) )
  2235.       AND
  2236.       PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, Items[i].Name, &Items[i].Flag, &Size )
  2237.     )
  2238.     {
  2239.       ;
  2240.     }
  2241.   }
  2242.  
  2243.  /***************************************************************************
  2244.   * Add items for each drive on the system.                    *
  2245.   ***************************************************************************/
  2246.  
  2247.   UpdateDriveList ( Anchor, Library, Profile, 0 ) ;
  2248.  
  2249.  /***************************************************************************
  2250.   * Get the window's current size and position.                             *
  2251.   ***************************************************************************/
  2252.  
  2253.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  2254.   Profile->fPosition = FALSE ;
  2255.   if
  2256.   (
  2257.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "Position", &Size )
  2258.     AND
  2259.     ( Size == sizeof(Profile->Position) )
  2260.     AND
  2261.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "Position", &Profile->Position, &Size )
  2262.   )
  2263.   {
  2264.     Profile->fPosition = TRUE ;
  2265.   }
  2266.  
  2267.  /***************************************************************************
  2268.   * Get the program options.                            *
  2269.   ***************************************************************************/
  2270.  
  2271.   Profile->HideControls = FALSE ;
  2272.   if
  2273.   (
  2274.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Size )
  2275.     AND
  2276.     ( Size == sizeof(Profile->HideControls) )
  2277.     AND
  2278.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Profile->HideControls, &Size )
  2279.   )
  2280.   {
  2281.     Profile->fHideControls = TRUE ;
  2282.   }
  2283.  
  2284.   Profile->TimerInterval = 1000 ;
  2285.   if
  2286.   (
  2287.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "TimerInterval", &Size )
  2288.     AND
  2289.     ( Size == sizeof(Profile->TimerInterval) )
  2290.     AND
  2291.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "TimerInterval", &Profile->TimerInterval, &Size )
  2292.   )
  2293.   {
  2294.     Profile->fTimerInterval = TRUE ;
  2295.   }
  2296.  
  2297.  /***************************************************************************
  2298.   * Get the presentation parameters.                        *
  2299.   ***************************************************************************/
  2300.  
  2301.   strcpy ( Profile->FontNameSize, "" ) ;
  2302.   Profile->fFontNameSize = FALSE ;
  2303.   if
  2304.   (
  2305.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Size )
  2306.     AND
  2307.     ( Size == sizeof(Profile->FontNameSize) )
  2308.     AND
  2309.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Profile->FontNameSize, &Size )
  2310.   )
  2311.   {
  2312.     Profile->fFontNameSize = TRUE ;
  2313.   }
  2314.  
  2315.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  2316.   Profile->fBackColor = FALSE ;
  2317.   if
  2318.   (
  2319.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Size )
  2320.     AND
  2321.     ( Size == sizeof(Profile->BackColor) )
  2322.     AND
  2323.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Profile->BackColor, &Size )
  2324.   )
  2325.   {
  2326.     Profile->fBackColor = TRUE ;
  2327.   }
  2328.  
  2329.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  2330.   Profile->fTextColor = FALSE ;
  2331.   if
  2332.   (
  2333.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Size )
  2334.     AND
  2335.     ( Size == sizeof(Profile->TextColor) )
  2336.     AND
  2337.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Profile->TextColor, &Size )
  2338.   )
  2339.   {
  2340.     Profile->fTextColor = TRUE ;
  2341.   }
  2342. }
  2343.  
  2344. /****************************************************************************
  2345.  *                                        *
  2346.  *                 Put Profile Data                    *
  2347.  *                                        *
  2348.  ****************************************************************************/
  2349.  
  2350. static void PutProfile ( PPROFILE Profile )
  2351. {
  2352.  /***************************************************************************
  2353.   * Local Declarations                                *
  2354.   ***************************************************************************/
  2355.  
  2356.   int i ;
  2357.  
  2358.  /***************************************************************************
  2359.   * Save the window's current size and position.                            *
  2360.   ***************************************************************************/
  2361.  
  2362.   PrfWriteProfileData
  2363.   (
  2364.     HINI_USERPROFILE,
  2365.     PROGRAM_NAME,
  2366.     "Position",
  2367.     &Profile->Position,
  2368.     (ULONG)sizeof(Profile->Position)
  2369.   ) ;
  2370.  
  2371.  /***************************************************************************
  2372.   * Save the program options.                            *
  2373.   ***************************************************************************/
  2374.  
  2375.   if ( Profile->fHideControls )
  2376.   {
  2377.     PrfWriteProfileData
  2378.     (
  2379.       HINI_USERPROFILE,
  2380.       PROGRAM_NAME,
  2381.       "HideControls",
  2382.       &Profile->HideControls,
  2383.       (ULONG)sizeof(Profile->HideControls)
  2384.     ) ;
  2385.   }
  2386.  
  2387.   if ( Profile->fTimerInterval )
  2388.   {
  2389.     PrfWriteProfileData
  2390.     (
  2391.       HINI_USERPROFILE,
  2392.       PROGRAM_NAME,
  2393.       "TimerInterval",
  2394.       &Profile->TimerInterval,
  2395.       (ULONG)sizeof(Profile->TimerInterval)
  2396.     ) ;
  2397.   }
  2398.  
  2399.  /***************************************************************************
  2400.   * Save the item options.                            *
  2401.   ***************************************************************************/
  2402.  
  2403.   for ( i=0; i<Profile->ItemCount; i++ )
  2404.   {
  2405.     PITEM Item = & Profile->Items [i] ;
  2406.  
  2407.     PrfWriteProfileData
  2408.     (
  2409.       HINI_USERPROFILE,
  2410.       PROGRAM_NAME,
  2411.       Item->Name,
  2412.       &Item->Flag,
  2413.       (ULONG)sizeof(Item->Flag)
  2414.     ) ;
  2415.   }
  2416.  
  2417.  /***************************************************************************
  2418.   * Save the presentation parameters.                        *
  2419.   ***************************************************************************/
  2420.  
  2421.   if ( Profile->fFontNameSize )
  2422.   {
  2423.     PrfWriteProfileData
  2424.     (
  2425.       HINI_USERPROFILE,
  2426.       PROGRAM_NAME,
  2427.       "FontNameSize",
  2428.       Profile->FontNameSize,
  2429.       (ULONG)sizeof(Profile->FontNameSize)
  2430.     ) ;
  2431.   }
  2432.  
  2433.   if ( Profile->fBackColor )
  2434.   {
  2435.     PrfWriteProfileData
  2436.     (
  2437.       HINI_USERPROFILE,
  2438.       PROGRAM_NAME,
  2439.       "BackgroundColor",
  2440.       &Profile->BackColor,
  2441.       (ULONG)sizeof(Profile->BackColor)
  2442.     ) ;
  2443.   }
  2444.  
  2445.   if ( Profile->fTextColor )
  2446.   {
  2447.     PrfWriteProfileData
  2448.     (
  2449.       HINI_USERPROFILE,
  2450.       PROGRAM_NAME,
  2451.       "ForegroundColor",
  2452.       &Profile->TextColor,
  2453.       (ULONG)sizeof(Profile->TextColor)
  2454.     ) ;
  2455.   }
  2456. }
  2457.  
  2458. /****************************************************************************
  2459.  *                                        *
  2460.  *    Scan CONFIG.SYS for a keyword.    Return the value.            *
  2461.  *                                        *
  2462.  ****************************************************************************/
  2463.  
  2464. static PCHAR ScanSystemConfig ( PCHAR Keyword )
  2465. {
  2466.  /***************************************************************************
  2467.   * Local Declarations                                *
  2468.   ***************************************************************************/
  2469.  
  2470.   static char Buffer [500] ;
  2471.   FILE *File ;
  2472.   SEL GlobalSelector ;
  2473.   SEL LocalSelector ;
  2474.   char Path [_MAX_PATH] ;
  2475.   GINFOSEG FAR *pGlobalInfoSeg ;
  2476.  
  2477.  /***************************************************************************
  2478.   * Get the boot drive number from the global information segment.        *
  2479.   ***************************************************************************/
  2480.  
  2481.   DosGetInfoSeg ( &GlobalSelector, &LocalSelector ) ;
  2482.  
  2483.   pGlobalInfoSeg = MAKEPGINFOSEG ( GlobalSelector ) ;
  2484.  
  2485.  /***************************************************************************
  2486.   * Build the CONFIG.SYS path.                            *
  2487.   ***************************************************************************/
  2488.  
  2489.   Path[0] = (char) ( pGlobalInfoSeg->bootdrive + 'A' - 1 ) ;
  2490.   Path[1] = 0 ;
  2491.   strcat ( Path, ":\\CONFIG.SYS" ) ;
  2492.  
  2493.  /***************************************************************************
  2494.   * Open CONFIG.SYS for reading.                        *
  2495.   ***************************************************************************/
  2496.  
  2497.   File = fopen ( Path, "rt" ) ;
  2498.   if ( NOT File )
  2499.   {
  2500.     return ( NULL ) ;
  2501.   }
  2502.  
  2503.  /***************************************************************************
  2504.   * While there're more lines in CONFIG.SYS, read a line and check it.      *
  2505.   ***************************************************************************/
  2506.  
  2507.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  2508.   {
  2509.  
  2510.    /*************************************************************************
  2511.     * Clean any trailing newline character from the input string.        *
  2512.     *************************************************************************/
  2513.  
  2514.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  2515.     {
  2516.       Buffer[strlen(Buffer)-1] = 0 ;
  2517.     }
  2518.  
  2519.    /*************************************************************************
  2520.     * If keyword starts the line, we've found the line we want.  Close      *
  2521.     *    the file and return a pointer to the parameter text.            *
  2522.     *************************************************************************/
  2523.  
  2524.     if ( NOT strnicmp ( Buffer, Keyword, strlen(Keyword) )
  2525.       AND ( Buffer[strlen(Keyword)] == '=' ) )
  2526.     {
  2527.       fclose ( File ) ;
  2528.       return ( Buffer + strlen(Keyword) + 1 ) ;
  2529.     }
  2530.   }
  2531.  
  2532.  /***************************************************************************
  2533.   * Close the file.  We haven't found the line we wanted.                   *
  2534.   ***************************************************************************/
  2535.  
  2536.   fclose ( File ) ;
  2537.  
  2538.   return ( NULL ) ;
  2539. }
  2540.  
  2541. /****************************************************************************
  2542.  *                                        *
  2543.  *             Resize Client Window                    *
  2544.  *                                        *
  2545.  ****************************************************************************/
  2546.  
  2547. static void ResizeWindow ( HWND hwnd, PPROFILE Profile )
  2548. {
  2549.  /***************************************************************************
  2550.   * Local Declarations                                *
  2551.   ***************************************************************************/
  2552.  
  2553.   SHORT Count ;
  2554.   SHORT fHadToHide = FALSE ;
  2555.   SHORT fHadToRestore = FALSE ;
  2556.   LONG Height ;
  2557.   HPS hPS ;
  2558.   HWND hwndFrame ;
  2559.   short i ;
  2560.   RECTL Rectangle ;
  2561.   char Text [100] ;
  2562.   LONG Widest ;
  2563.  
  2564.  /***************************************************************************
  2565.   * If the window is visible and minimized, restore it invisibly.        *
  2566.   ***************************************************************************/
  2567.  
  2568.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  2569.  
  2570.   if ( Profile->Position.fs & SWP_MINIMIZE )
  2571.   {
  2572.     if ( WinIsWindowVisible ( hwndFrame ) )
  2573.     {
  2574.       WinShowWindow ( hwndFrame, FALSE ) ;
  2575.       fHadToHide = TRUE ;
  2576.     }
  2577.     WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE ) ;
  2578.     fHadToRestore = TRUE ;
  2579.   }
  2580.  
  2581.  /***************************************************************************
  2582.   * Determine how many items are to be displayed.                *
  2583.   ***************************************************************************/
  2584.  
  2585.   hPS = WinGetPS ( hwnd ) ;
  2586.  
  2587.   Count = 0 ;
  2588.   Widest = 0 ;
  2589.   Height = 0 ;
  2590.  
  2591.   for ( i=0; i<Profile->ItemCount; i++ )
  2592.   {
  2593.     PITEM Item = & Profile->Items [i] ;
  2594.  
  2595.     if ( Item->Flag )
  2596.     {
  2597.       Count ++ ;
  2598.  
  2599.       sprintf ( Text, "%s 1,234,567K", Item->Label ) ;
  2600.  
  2601.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  2602.  
  2603.       WinDrawText ( hPS, strlen(Text), Text,
  2604.     &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  2605.  
  2606.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft+1) ) ;
  2607.  
  2608.       Height += Rectangle.yTop - Rectangle.yBottom ;
  2609.     }
  2610.   }
  2611.  
  2612.   WinReleasePS ( hPS ) ;
  2613.  
  2614.  /***************************************************************************
  2615.   * Get the window's current size & position.                               *
  2616.   ***************************************************************************/
  2617.  
  2618.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  2619.  
  2620.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2621.  
  2622.  /***************************************************************************
  2623.   * Adjust the window's width & height.                                     *
  2624.   ***************************************************************************/
  2625.  
  2626.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  2627.  
  2628.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  2629.  
  2630.  /***************************************************************************
  2631.   * Compute new frame size and apply it.                    *
  2632.   ***************************************************************************/
  2633.  
  2634.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2635.  
  2636.   WinSetWindowPos ( hwndFrame, NULL, 0, 0,
  2637.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2638.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2639.     SWP_SIZE ) ;
  2640.  
  2641.  /***************************************************************************
  2642.   * Return the window to its original state.                    *
  2643.   ***************************************************************************/
  2644.  
  2645.   if ( fHadToRestore )
  2646.   {
  2647.     WinSetWindowPos ( hwndFrame, NULL,
  2648.       Profile->Position.x, Profile->Position.y,
  2649.       Profile->Position.cx, Profile->Position.cy,
  2650.       SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
  2651.   }
  2652.  
  2653.   if ( fHadToHide )
  2654.   {
  2655.     WinShowWindow ( hwndFrame, TRUE ) ;
  2656.   }
  2657.  
  2658.  /***************************************************************************
  2659.   * Invalidate the window so that it gets repainted.                *
  2660.   ***************************************************************************/
  2661.  
  2662.   WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  2663. }
  2664.  
  2665. /****************************************************************************
  2666.  *                                        *
  2667.  *            Hide Window Controls                    *
  2668.  *                                        *
  2669.  ****************************************************************************/
  2670.  
  2671. static void HideControls
  2672. (
  2673.   BOOL fHide,
  2674.   HWND hwndFrame,
  2675.   HWND hwndSysMenu,
  2676.   HWND hwndTitleBar,
  2677.   HWND hwndMinMax
  2678. )
  2679. {
  2680.  /***************************************************************************
  2681.   * Local Declarations                                *
  2682.   ***************************************************************************/
  2683.  
  2684.   SWP OldPosition ;
  2685.   SWP Position ;
  2686.   RECTL Rectangle ;
  2687.   BOOL WasVisible ;
  2688.  
  2689.  /***************************************************************************
  2690.   * Get original window position and state.                    *
  2691.   ***************************************************************************/
  2692.  
  2693.   WinQueryWindowPos ( hwndFrame, &OldPosition ) ;
  2694.  
  2695.   WasVisible = WinIsWindowVisible ( hwndFrame ) ;
  2696.  
  2697.  /***************************************************************************
  2698.   * Restore and hide the window.                        *
  2699.   ***************************************************************************/
  2700.  
  2701.   WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE | SWP_HIDE ) ;
  2702.  
  2703.  /***************************************************************************
  2704.   * Determine client window and location.                    *
  2705.   ***************************************************************************/
  2706.  
  2707.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  2708.  
  2709.   Rectangle.xLeft   = Position.x ;
  2710.   Rectangle.xRight  = Position.x + Position.cx ;
  2711.   Rectangle.yBottom = Position.y ;
  2712.   Rectangle.yTop    = Position.y + Position.cy ;
  2713.  
  2714.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2715.  
  2716.  /***************************************************************************
  2717.   * Hide or reveal the controls windows by changing their parentage.        *
  2718.   ***************************************************************************/
  2719.  
  2720.   if ( fHide )
  2721.   {
  2722.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2723.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2724.     WinSetParent ( hwndMinMax,     HWND_OBJECT, FALSE ) ;
  2725.   }
  2726.   else
  2727.   {
  2728.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2729.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2730.     WinSetParent ( hwndMinMax,     hwndFrame, TRUE ) ;
  2731.   }
  2732.  
  2733.  /***************************************************************************
  2734.   * Tell the frame that things have changed.  Let it update the window.     *
  2735.   ***************************************************************************/
  2736.  
  2737.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2738.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2739.  
  2740.  /***************************************************************************
  2741.   * Reposition the frame around the client window, which is left be.        *
  2742.   ***************************************************************************/
  2743.  
  2744.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2745.  
  2746.   WinSetWindowPos ( hwndFrame, NULL,
  2747.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2748.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2749.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2750.     SWP_SIZE | SWP_MOVE ) ;
  2751.  
  2752.  /***************************************************************************
  2753.   * If window was maximized, put it back that way.                *
  2754.   ***************************************************************************/
  2755.  
  2756.   if ( OldPosition.fs & SWP_MAXIMIZE )
  2757.   {
  2758.     WinSetWindowPos ( hwndFrame, NULL,
  2759.       (SHORT) Rectangle.xLeft,    (SHORT) Rectangle.yBottom,
  2760.       (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2761.       (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2762.       SWP_SIZE | SWP_MOVE |
  2763.       ( OldPosition.fs & SWP_MAXIMIZE ) ) ;
  2764.   }
  2765.  
  2766.  /***************************************************************************
  2767.   * If the window was visible in the first place, show it.            *
  2768.   ***************************************************************************/
  2769.  
  2770.   if ( WasVisible )
  2771.   {
  2772.     WinShowWindow ( hwndFrame, TRUE ) ;
  2773.   }
  2774. }
  2775.  
  2776. /****************************************************************************
  2777.  *                                        *
  2778.  *    Update Window                                *
  2779.  *                                        *
  2780.  ****************************************************************************/
  2781.  
  2782. #pragma optimize ( "gle", off )
  2783.  
  2784. static void UpdateWindow ( HWND hwnd, PDATA Data, BOOL All )
  2785. {
  2786.  /***************************************************************************
  2787.   *                Declarations                    *
  2788.   ***************************************************************************/
  2789.  
  2790.   int Count ;
  2791.   HPS hPS ;
  2792.   short i ;
  2793.   RECTL Rectangle ;
  2794.   char Text [100] ;
  2795.  
  2796.  /***************************************************************************
  2797.   * Determine how many items are to be displayed.                *
  2798.   ***************************************************************************/
  2799.  
  2800.   Count = 0 ;
  2801.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2802.   {
  2803.     if ( Data->Profile.Items[i].Flag )
  2804.     {
  2805.       Count ++ ;
  2806.     }
  2807.   }
  2808.  
  2809.  /***************************************************************************
  2810.   * Get presentation space and make it use RGB colors.                *
  2811.   ***************************************************************************/
  2812.  
  2813.   hPS = WinGetPS ( hwnd ) ;
  2814.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  2815.  
  2816.  /***************************************************************************
  2817.   * Get the window's size and determine the initial position.               *
  2818.   ***************************************************************************/
  2819.  
  2820.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2821.  
  2822.   Rectangle.xLeft += Data->Width / 2 ;
  2823.   Rectangle.xRight -= Data->Width / 2 ;
  2824.  
  2825.   Rectangle.yBottom = Data->Height * ( Count - 1 ) ;
  2826.   Rectangle.yTop = Rectangle.yBottom + Data->Height ;
  2827.  
  2828.  /***************************************************************************
  2829.   * Review all items.  Display those changed, or all.                *
  2830.   ***************************************************************************/
  2831.  
  2832.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2833.   {
  2834.     PITEM Item = & Data->Profile.Items [i] ;
  2835.     ULONG NewValue ;
  2836.  
  2837.     if ( Item->Flag )
  2838.     {
  2839.       NewValue = Item->NewValue ( Data, Item->Parm ) ;
  2840.  
  2841.       if ( All OR ( NewValue != Item->Value ) )
  2842.       {
  2843.     switch ( i )
  2844.     {
  2845.       case ITEM_CLOCK:
  2846.       {
  2847.         ULONG Month  = ( NewValue % 100000000L ) / 1000000L ;
  2848.         ULONG Day     = ( NewValue % 1000000L ) / 10000L ;
  2849.         ULONG Hour     = ( NewValue % 10000L ) / 100L ;
  2850.         ULONG Minute = ( NewValue % 100L ) ;
  2851.  
  2852.         switch ( Data->CountryInfo.fsDateFmt )
  2853.         {
  2854.           case DATEFMT_DD_MM_YY:
  2855.         sprintf ( Text, "%02lu%s%02lu ",
  2856.           Day, Data->CountryInfo.szDateSeparator, Month ) ;
  2857.         break ;
  2858.  
  2859.           case DATEFMT_YY_MM_DD:
  2860.           case DATEFMT_MM_DD_YY:
  2861.           default:
  2862.         sprintf ( Text, "%02lu%s%02lu ",
  2863.           Month, Data->CountryInfo.szDateSeparator, Day ) ;
  2864.         break ;
  2865.         }
  2866.  
  2867.         if ( Data->CountryInfo.fsTimeFmt )
  2868.         {
  2869.           sprintf ( Text+strlen(Text), "%02lu%s%02lu",
  2870.         Hour,
  2871.         Data->CountryInfo.szTimeSeparator,
  2872.         Minute ) ;
  2873.         }
  2874.         else
  2875.         {
  2876.           PCHAR AmPm ;
  2877.  
  2878.           if ( Hour )
  2879.           {
  2880.         if ( Hour < 12 )
  2881.         {
  2882.           AmPm = "a" ;
  2883.         }
  2884.         else if ( Hour == 12 )
  2885.         {
  2886.           if ( Minute )
  2887.             AmPm = "p" ;
  2888.           else
  2889.             AmPm = "a" ;
  2890.         }
  2891.         else if ( Hour > 12 )
  2892.         {
  2893.           Hour -= 12 ;
  2894.           AmPm = "p" ;
  2895.         }
  2896.           }
  2897.           else
  2898.           {
  2899.         Hour = 12 ;
  2900.         if ( Minute )
  2901.           AmPm = "a" ;
  2902.         else
  2903.           AmPm = "p" ;
  2904.           }
  2905.           sprintf ( Text+strlen(Text), "%02lu%s%02lu%s",
  2906.         Hour, Data->CountryInfo.szTimeSeparator, Minute, AmPm ) ;
  2907.         }
  2908.         break ;
  2909.       }
  2910.  
  2911.       default:
  2912.       {
  2913.         memset ( Text, 0, sizeof(Text) ) ;
  2914.  
  2915.         if ( NewValue == DRIVE_ERROR )
  2916.         {
  2917.           WinLoadString ( Data->Anchor, Data->Library, IDS_DRIVEERROR, sizeof(Text), Text ) ;
  2918.         }
  2919.         else
  2920.         {
  2921.           if ( Item->Divisor )
  2922.           {
  2923.         if ( NewValue < Item->Divisor * 1000 )
  2924.           sprintf ( Text, "%lu", NewValue ) ;
  2925.         else
  2926.           sprintf ( Text, "%lu", (NewValue+Item->Divisor/2)/Item->Divisor ) ;
  2927.           }
  2928.           else
  2929.           {
  2930.         sprintf ( Text, "%lu", NewValue ) ;
  2931.           }
  2932.  
  2933.           {
  2934.         PCHAR p1, p2 ;
  2935.         CHAR Work[100] ;
  2936.  
  2937.         p1 = Text ;
  2938.         p2 = Work ;
  2939.         while ( *p1 )
  2940.         {
  2941.           *p2 = *p1 ;
  2942.           p1 ++ ;
  2943.           p2 ++ ;
  2944.           if ( *p1 )
  2945.           {
  2946.             if ( strlen(p1) % 3 == 0 )
  2947.             {
  2948.               *p2 = Data->CountryInfo.szThousandsSeparator [0] ;
  2949.               p2 ++ ;
  2950.             }
  2951.           }
  2952.         }
  2953.         *p2 = 0 ;
  2954.         strcpy ( Text, Work ) ;
  2955.           }
  2956.  
  2957.           if ( Item->Divisor )
  2958.           {
  2959.         if ( NewValue < Item->Divisor * 1000 )
  2960.           Text[strlen(Text)] = ' ' ;
  2961.         else
  2962.           Text[strlen(Text)] = Item->Suffix ;
  2963.           }
  2964.           else
  2965.           {
  2966.         Text[strlen(Text)] = Item->Suffix ;
  2967.           }
  2968.         }
  2969.       }
  2970.     }
  2971.  
  2972.     WinDrawText ( hPS, strlen(Text), Text, &Rectangle,
  2973.       Data->Profile.TextColor, Data->Profile.BackColor,
  2974.       DT_RIGHT | DT_BOTTOM | DT_ERASERECT ) ;
  2975.  
  2976.     WinDrawText ( hPS, strlen(Item->Label), Item->Label, &Rectangle,
  2977.       Data->Profile.TextColor, Data->Profile.BackColor,
  2978.       DT_LEFT | DT_BOTTOM ) ;
  2979.  
  2980.     Item->Value = NewValue ;
  2981.       }
  2982.       Rectangle.yBottom -= Data->Height ;
  2983.       Rectangle.yTop    -= Data->Height ;
  2984.     }
  2985.   }
  2986.  
  2987.  /***************************************************************************
  2988.   * Release the presentation space and return.                    *
  2989.   ***************************************************************************/
  2990.  
  2991.   WinReleasePS ( hPS ) ;
  2992. }
  2993.  
  2994. #pragma optimize ( "gle", on )
  2995.  
  2996.  
  2997. /****************************************************************************
  2998.  *                                        *
  2999.  *    Compute Time                                *
  3000.  *                                        *
  3001.  ****************************************************************************/
  3002.  
  3003. static ULONG ComputeTime ( PDATA Data, USHORT Dummy )
  3004. {
  3005.   char DateString [9] ;
  3006.   short Hour, Minute ;
  3007.   short Month, Day ;
  3008.   ULONG Time ;
  3009.   char TimeString [9] ;
  3010.  
  3011.   _strdate ( DateString ) ;
  3012.   _strtime ( TimeString ) ;
  3013.  
  3014.   Hour     = atoi ( TimeString + 0 ) ;
  3015.   Minute = atoi ( TimeString + 3 ) ;
  3016.  
  3017.   Month  = atoi ( DateString + 0 ) ;
  3018.   Day     = atoi ( DateString + 3 ) ;
  3019.  
  3020.   Time = Month ;
  3021.   Time *= 100 ;
  3022.   Time += Day ;
  3023.   Time *= 100 ;
  3024.   Time += Hour ;
  3025.   Time *= 100 ;
  3026.   Time += Minute ;
  3027.  
  3028.   return ( Time ) ;
  3029. }
  3030.  
  3031. /****************************************************************************
  3032.  *                                        *
  3033.  *    Compute Available Memory                            *
  3034.  *                                        *
  3035.  ****************************************************************************/
  3036.  
  3037. static ULONG ComputeFreeMemory ( PDATA Data, USHORT Dummy )
  3038. {
  3039.   ULONG MemFree ;
  3040.  
  3041.   DosMemAvail ( &MemFree ) ;
  3042.  
  3043.   return ( MemFree ) ;
  3044. }
  3045.  
  3046. /****************************************************************************
  3047.  *                                        *
  3048.  *    Compute Swap-File Size                            *
  3049.  *                                        *
  3050.  ****************************************************************************/
  3051.  
  3052. static ULONG ComputeSwapSize ( PDATA Data, USHORT Dummy )
  3053. {
  3054.  /***************************************************************************
  3055.   *                Declarations                    *
  3056.   ***************************************************************************/
  3057.  
  3058.   char Path [_MAX_PATH+1] ;
  3059.   struct stat Status ;
  3060.   ULONG SwapSize ;
  3061.  
  3062.  /***************************************************************************
  3063.   * Find the swap file and find its size.                    *
  3064.   ***************************************************************************/
  3065.  
  3066.   strcpy ( Path, Data->SwapPath ) ;
  3067.  
  3068.   if ( Path[strlen(Path)-1] != '\\' )
  3069.   {
  3070.     strcat ( Path, "\\" ) ;
  3071.   }
  3072.  
  3073.   strcat ( Path, "SWAPPER.DAT" ) ;
  3074.  
  3075.   SwapSize = 0 ;
  3076.   if ( stat ( Path, &Status ) == 0 )
  3077.   {
  3078.     SwapSize = Status.st_size ;
  3079.   }
  3080.  
  3081.   return ( SwapSize ) ;
  3082. }
  3083.  
  3084. /****************************************************************************
  3085.  *                                        *
  3086.  *    Compute Available Swap Space                        *
  3087.  *                                        *
  3088.  ****************************************************************************/
  3089.  
  3090. static ULONG ComputeSwapFree ( PDATA Data, USHORT Dummy )
  3091. {
  3092.  /***************************************************************************
  3093.   *                Declarations                    *
  3094.   ***************************************************************************/
  3095.  
  3096.   FSALLOCATE Allocation ;
  3097.   char Path [_MAX_PATH+1] ;
  3098.   ULONG SwapFree ;
  3099.  
  3100.  /***************************************************************************
  3101.   * Find the swap file and find its size.                    *
  3102.   ***************************************************************************/
  3103.  
  3104.   strcpy ( Path, Data->SwapPath ) ;
  3105.   strcat ( Path, "\\SWAPPER.DAT" ) ;
  3106.  
  3107.  /***************************************************************************
  3108.   * Compute swap device free space.                        *
  3109.   ***************************************************************************/
  3110.  
  3111.   SwapFree = 0 ;
  3112.   if ( Path[0] )
  3113.   {
  3114.     DosQFSInfo ( Path[0]-'A'+1, FSIL_ALLOC,
  3115.       (PBYTE)&Allocation, sizeof(Allocation) ) ;
  3116.  
  3117.     SwapFree = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  3118.   }
  3119.  
  3120.  /***************************************************************************
  3121.   * Return swap device's free space, less the minimum free space.           *
  3122.   ***************************************************************************/
  3123.  
  3124.   if ( SwapFree < (ULONG)Data->MinFree*1024L )
  3125.     return ( 0L ) ;
  3126.   else
  3127.     return ( SwapFree - (ULONG)Data->MinFree * 1024L ) ;
  3128. }
  3129.  
  3130. /****************************************************************************
  3131.  *                                        *
  3132.  *    Compute Spool-file Size                            *
  3133.  *                                        *
  3134.  ****************************************************************************/
  3135.  
  3136. static ULONG ComputeSpoolSize ( PDATA Data, USHORT Dummy )
  3137. {
  3138.  /***************************************************************************
  3139.   *                Declarations                    *
  3140.   ***************************************************************************/
  3141.  
  3142.   USHORT Count ;
  3143.   FILEFINDBUF *Found ;
  3144.   HDIR hDir = HDIR_CREATE ;
  3145.   BYTE *Path ;
  3146.   USHORT PathSize ;
  3147.   ULONG TotalSize = 0 ;
  3148.  
  3149.  /***************************************************************************
  3150.   * Build file specifier for the spool directory.                *
  3151.   ***************************************************************************/
  3152.  
  3153.   DosQSysInfo ( 0, (PBYTE)&PathSize, sizeof(PathSize) ) ;
  3154.  
  3155.   Path = malloc ( PathSize ) ;
  3156.   if ( Path == NULL )
  3157.   {
  3158.     return ( 0 ) ;
  3159.   }
  3160.  
  3161.   Found = malloc ( PathSize + sizeof(FILEFINDBUF) ) ;
  3162.   if ( Found == NULL )
  3163.   {
  3164.     free ( Path ) ;
  3165.     return ( 0 ) ;
  3166.   }
  3167.  
  3168.   strcpy ( Path, Data->SpoolPath ) ;
  3169.   strcat ( Path, "\\*.*" ) ;
  3170.  
  3171.  /***************************************************************************
  3172.   * If there are any files/directories in the spool directory . . .        *
  3173.   ***************************************************************************/
  3174.  
  3175.   Count = 1 ;
  3176.   if ( !DosFindFirst2 ( Path, &hDir,
  3177.     FILE_NORMAL | FILE_READONLY | FILE_DIRECTORY | FILE_ARCHIVED,
  3178.     Found, PathSize+sizeof(FILEFINDBUF), &Count, FIL_STANDARD, 0L ) )
  3179.   {
  3180.  
  3181.    /*************************************************************************
  3182.     * Loop through every entry in the spool directory.                *
  3183.     *************************************************************************/
  3184.  
  3185.     do
  3186.     {
  3187.  
  3188.      /***********************************************************************
  3189.       * Ignore the parent and current directory entries.            *
  3190.       ***********************************************************************/
  3191.  
  3192.       if ( !strcmp ( Found->achName, "." )
  3193.     OR !strcmp ( Found->achName, ".." ) )
  3194.       {
  3195.     continue ;
  3196.       }
  3197.  
  3198.      /***********************************************************************
  3199.       * If the entry is a subdirectory . . .                    *
  3200.       ***********************************************************************/
  3201.  
  3202.       if ( Found->attrFile & FILE_DIRECTORY )
  3203.       {
  3204.  
  3205.        /*********************************************************************
  3206.     * Scan the subdirectory and add every file's size to the total.     *
  3207.     *********************************************************************/
  3208.  
  3209.     HDIR hDir = HDIR_CREATE ;
  3210.  
  3211.     strcpy ( Path, Data->SpoolPath ) ;
  3212.     strcat ( Path, "\\" ) ;
  3213.     strcat ( Path, Found->achName ) ;
  3214.     strcat ( Path, "\\*.*" ) ;
  3215.  
  3216.     Count = 1 ;
  3217.     if ( !DosFindFirst2 ( Path, &hDir,
  3218.       FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED,
  3219.       Found, PathSize+sizeof(FILEFINDBUF), &Count, FIL_STANDARD, 0L ) )
  3220.     {
  3221.       do
  3222.       {
  3223.         TotalSize += Found->cbFileAlloc ;
  3224.       }
  3225.       while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF), &Count ) ) ;
  3226.       DosFindClose ( hDir ) ;
  3227.     }
  3228.  
  3229.     Count = 1 ;
  3230.       }
  3231.  
  3232.      /***********************************************************************
  3233.       * Else if it was a file, add its size to the total.            *
  3234.       ***********************************************************************/
  3235.  
  3236.       else
  3237.       {
  3238.     TotalSize += Found->cbFileAlloc ;
  3239.       }
  3240.     }
  3241.     while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF), &Count ) ) ;
  3242.  
  3243.    /*************************************************************************
  3244.     * Close the directory scan.                         *
  3245.     *************************************************************************/
  3246.  
  3247.     DosFindClose ( hDir ) ;
  3248.   }
  3249.  
  3250.   free ( Path ) ;
  3251.   free ( Found ) ;
  3252.  
  3253.   return ( TotalSize ) ;
  3254. }
  3255.  
  3256. /****************************************************************************
  3257.  *                                        *
  3258.  *    Compute CPU Load                                *
  3259.  *                                        *
  3260.  ****************************************************************************/
  3261.  
  3262. static ULONG ComputeCpuLoad ( PDATA Data, USHORT Dummy )
  3263. {
  3264.   ULONG Load ;
  3265.  
  3266.   Data->MaxCount = (ULONG) max ( Data->MaxCount, Data->IdleCount ) ;
  3267.  
  3268.   Load = ( ( Data->MaxCount - Data->IdleCount ) * 100 ) / Data->MaxCount ;
  3269.  
  3270.   return ( Load ) ;
  3271. }
  3272.  
  3273. /****************************************************************************
  3274.  *                                        *
  3275.  *    Compute Active Task Count                         *
  3276.  *                                        *
  3277.  ****************************************************************************/
  3278.  
  3279. static ULONG ComputeTaskCount ( PDATA Data, USHORT Dummy )
  3280. {
  3281.   return ( WinQuerySwitchList ( Data->Anchor, NULL, 0 ) ) ;
  3282. }
  3283.  
  3284. /****************************************************************************
  3285.  *                                        *
  3286.  *    Compute Drive Free Space                            *
  3287.  *                                        *
  3288.  ****************************************************************************/
  3289.  
  3290. static ULONG ComputeDriveFree ( PDATA Data, USHORT Drive )
  3291. {
  3292.   FSALLOCATE Allocation ;
  3293.  
  3294.   if ( DosQFSInfo ( Drive, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) )
  3295.     return ( DRIVE_ERROR ) ;
  3296.  
  3297.   return ( Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ) ;
  3298. }
  3299.  
  3300. /****************************************************************************
  3301.  *                                        *
  3302.  *    Monitor Loop Thread                            *
  3303.  *                                        *
  3304.  ****************************************************************************/
  3305.  
  3306. static void _far _cdecl MonitorLoopThread ( PMONITOR_PARMS Parms )
  3307. {
  3308.  /***************************************************************************
  3309.   * Local Declarations                                *
  3310.   ***************************************************************************/
  3311.  
  3312.   ULONG     Counter ;
  3313.   ULONG     CurrentCounter ;
  3314.   ULONG     DeltaMilliseconds ;
  3315.   BOOL        HiResTimer ;
  3316.   ULONG     LastCounter ;
  3317.   ULONG     LastMilliseconds ;
  3318.   ULONG     Nanoseconds ;
  3319.   PGINFOSEG pGlobalInfoSeg = NULL ;
  3320.   PLINFOSEG pLocalInfoSeg = NULL ;
  3321.   TIMESTAMP Time [2] ;
  3322.  
  3323.  /***************************************************************************
  3324.   * Set this thread's priority as high as it can go.                        *
  3325.   ***************************************************************************/
  3326.  
  3327.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, *_threadid  ) ;
  3328.  
  3329.  /***************************************************************************
  3330.   * Get pointer to global information segment, where the time is kept.        *
  3331.   ***************************************************************************/
  3332.  
  3333.   DosGetInfoSeg ( &SELECTOROF(pGlobalInfoSeg), &SELECTOROF(pLocalInfoSeg) ) ;
  3334.  
  3335.  /***************************************************************************
  3336.   * Start up the high resolution timer, if it is available.            *
  3337.   ***************************************************************************/
  3338.  
  3339.   HiResTimer = OpenTimer ( ) ;
  3340.  
  3341.  /***************************************************************************
  3342.   * Loop forever . . .                                *
  3343.   ***************************************************************************/
  3344.  
  3345.   while ( 1 )
  3346.   {
  3347.  
  3348.    /*************************************************************************
  3349.     * Reset the last time and count seen.                    *
  3350.     *************************************************************************/
  3351.  
  3352.     if ( HiResTimer )
  3353.       GetTime ( &Time[0] ) ;
  3354.     else
  3355.       LastMilliseconds = pGlobalInfoSeg->msecs ;
  3356.  
  3357.     LastCounter = *Parms->Counter ;
  3358.  
  3359.    /*************************************************************************
  3360.     * Sleep for a bit.                                *
  3361.     *************************************************************************/
  3362.  
  3363.     DosSleep ( *Parms->Interval ) ;
  3364.  
  3365.    /*************************************************************************
  3366.     * Find out how much time and counts went by.                *
  3367.     *************************************************************************/
  3368.  
  3369.     CurrentCounter = *Parms->Counter ;
  3370.  
  3371.     if ( HiResTimer )
  3372.     {
  3373.       GetTime ( &Time[1] ) ;
  3374.       DeltaMilliseconds = ElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  3375.       if ( Nanoseconds >= 500000L )
  3376.     DeltaMilliseconds ++ ;
  3377.     }
  3378.     else
  3379.     {
  3380.       DeltaMilliseconds = pGlobalInfoSeg->msecs - LastMilliseconds ;
  3381.     }
  3382.  
  3383.    /*************************************************************************
  3384.     * Find out how much idle time was counted.    Adjust it to persecond.     *
  3385.     *************************************************************************/
  3386.  
  3387.     Counter = ( (CurrentCounter-LastCounter) * 1000 ) / DeltaMilliseconds ;
  3388.  
  3389.    /*************************************************************************
  3390.     * Tell the owner window to refresh its statistics.                *
  3391.     *************************************************************************/
  3392.  
  3393.     WinPostMsg ( Parms->Owner, WM_REFRESH, MPFROMLONG(Counter), 0L ) ;
  3394.   }
  3395. }
  3396.  
  3397. /****************************************************************************
  3398.  *                                        *
  3399.  *    Update the Item List to reflect changes in the available drives.    *
  3400.  *                                        *
  3401.  ****************************************************************************/
  3402.  
  3403. static VOID UpdateDriveList
  3404. (
  3405.   HAB Anchor,
  3406.   HMODULE Library,
  3407.   PPROFILE Profile,
  3408.   ULONG OldDrives
  3409. )
  3410. {
  3411.  /***************************************************************************
  3412.   * Local Declarations                                *
  3413.   ***************************************************************************/
  3414.  
  3415.   USHORT Count ;
  3416.   USHORT Drive ;
  3417.   ULONG Drives ;
  3418.   SHORT i ;
  3419.   USHORT OldCount ;
  3420.   USHORT OldIndex ;
  3421.   ITEM OldItems [ ITEM_BASE_COUNT + MAX_DRIVES ] ;
  3422.   ULONG Size ;
  3423.  
  3424.   CHAR LabelFormat [80] ;
  3425.   CHAR OptionFormat [80] ;
  3426.  
  3427.  /***************************************************************************
  3428.   * Get format strings.                             *
  3429.   ***************************************************************************/
  3430.  
  3431.   WinLoadString ( Anchor, Library, IDS_SHOW_DRIVE_FREE_LABEL, sizeof(LabelFormat), LabelFormat ) ;
  3432.   WinLoadString ( Anchor, Library, IDS_SHOW_DRIVE_FREE_OPTION, sizeof(OptionFormat), OptionFormat ) ;
  3433.  
  3434.  /***************************************************************************
  3435.   * Save the old item list for comparison.                    *
  3436.   ***************************************************************************/
  3437.  
  3438.   OldCount = 0 ;
  3439.   memset ( OldItems, 0, sizeof(OldItems) ) ;
  3440.  
  3441.   if ( OldDrives )
  3442.   {
  3443.     OldCount = Profile->ItemCount ;
  3444.     memcpy ( OldItems, Items, sizeof(OldItems) ) ;
  3445.   }
  3446.  
  3447.  /***************************************************************************
  3448.   * Add items for each drive on the system.                    *
  3449.   ***************************************************************************/
  3450.  
  3451.   Count = ITEM_BASE_COUNT ;
  3452.   OldIndex = ITEM_BASE_COUNT ;
  3453.  
  3454.   DosQCurDisk ( &Drive, &Drives ) ;
  3455.  
  3456.   Drives >>= 2 ;
  3457.   OldDrives >>= 2 ;
  3458.  
  3459.   for ( Drive=3; Drive<MAX_DRIVES; Drive++ )
  3460.   {
  3461.     while ( ( OldIndex < OldCount )
  3462.       AND ( (SHORT)OldItems[OldIndex].MenuId < IDM_SHOW_DRIVE_FREE + Drive ) )
  3463.     {
  3464.       OldIndex ++ ;
  3465.     }
  3466.  
  3467.     if ( Drives & 1 )
  3468.     {
  3469.       if ( OldDrives & 1 )
  3470.       {
  3471.     Items[Count++] = OldItems[OldIndex++] ;
  3472.       }
  3473.       else
  3474.       {
  3475.     if ( CheckDrive ( Drive ) )
  3476.     {
  3477.       sprintf ( Items[Count].Name,         "ShowDrive%c:", Drive+'A'-1 ) ;
  3478.       sprintf ( Items[Count].Label,      LabelFormat,    Drive+'A'-1 ) ;
  3479.       sprintf ( Items[Count].MenuOption, OptionFormat,   Drive+'A'-1 ) ;
  3480.  
  3481.       Items[Count].MenuId = IDM_SHOW_DRIVE_FREE + Drive ;
  3482.       Items[Count].NewValue = ComputeDriveFree ;
  3483.       Items[Count].Parm = Drive ;
  3484.       Items[Count].Divisor = 1024 ;
  3485.       Items[Count].Suffix = 'K' ;
  3486.       Count ++ ;
  3487.     }
  3488.       }
  3489.     }
  3490.  
  3491.     Drives >>= 1 ;
  3492.     OldDrives >>= 1 ;
  3493.   }
  3494.  
  3495.  /***************************************************************************
  3496.   * Save pointer to fixed configuration information.                *
  3497.   ***************************************************************************/
  3498.  
  3499.   Profile->Items = Items ;
  3500.   Profile->ItemCount = Count ;
  3501.  
  3502.  /***************************************************************************
  3503.   * Fetch the display flags for the drives.                    *
  3504.   ***************************************************************************/
  3505.  
  3506.   for ( i=ITEM_BASE_COUNT; i<Profile->ItemCount; i++ )
  3507.   {
  3508.     PITEM Item = & Profile->Items [i] ;
  3509.  
  3510.     Item->Flag = TRUE ;
  3511.     if
  3512.     (
  3513.       PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Size )
  3514.       AND
  3515.       ( Size == sizeof(Item->Flag) )
  3516.       AND
  3517.       PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Item->Flag, &Size )
  3518.     )
  3519.     {
  3520.       ;
  3521.     }
  3522.   }
  3523. }
  3524.  
  3525. /****************************************************************************
  3526.  *                                        *
  3527.  *    Check to see if drive should be added to display list.            *
  3528.  *                                        *
  3529.  ****************************************************************************/
  3530.  
  3531. static BOOL CheckDrive ( USHORT Drive )
  3532. {
  3533.  /***************************************************************************
  3534.   * Local Declarations                                *
  3535.   ***************************************************************************/
  3536.  
  3537.   USHORT Action ;
  3538.   BOOL     Addit = FALSE ;
  3539.   USHORT Handle ;
  3540.   USHORT Status ;
  3541.   BYTE     Path [3] ;
  3542.  
  3543.  /***************************************************************************
  3544.   * Attempt to open the drive as an entire device.                *
  3545.   ***************************************************************************/
  3546.  
  3547.   Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  3548.   Path[1] = ':' ;
  3549.   Path[2] = 0 ;
  3550.  
  3551.   Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  3552.     OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  3553.     OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  3554.  
  3555.  /***************************************************************************
  3556.   * Process return code.                            *
  3557.   ***************************************************************************/
  3558.  
  3559.   switch ( Status )
  3560.   {
  3561.  
  3562.    /*************************************************************************
  3563.     * No error?  Check to see if removable media (floppies, CDs).  If media *
  3564.     *    can be removed, don't try to monitor it.                            *
  3565.     *************************************************************************/
  3566.  
  3567.     case 0:
  3568.     {
  3569.       BIOSPARAMETERBLOCK BiosParms ;
  3570.       BYTE Command = 0 ;
  3571.  
  3572.       if ( !DosDevIOCtl ( &BiosParms, &Command, DSK_GETDEVICEPARAMS, IOCTL_DISK, Handle ) )
  3573.       {
  3574.     if ( BiosParms.fsDeviceAttr & 1 )  // Must be FIXED drive.
  3575.     {
  3576.       Addit = TRUE ;
  3577.     }
  3578.       }
  3579.       DosClose ( Handle ) ;
  3580.       break ;
  3581.     }
  3582.  
  3583.    /*************************************************************************
  3584.     * Drive not ready?    Had to be a floppy or CD-ROM without a disk in it.  *
  3585.     *    We don't monitor floppies nor CDs.                                  *
  3586.     *************************************************************************/
  3587.  
  3588.     case ERROR_NOT_READY:
  3589.       break ;
  3590.  
  3591.    /*************************************************************************
  3592.     * Path not found, or bad network name?  Had to be a network drive        *
  3593.     *    that was still defined but had lost its session.  Don't watch it,   *
  3594.     *    since it will have to be disconnected and then reconnected in order *
  3595.     *    to work.                                *
  3596.     *************************************************************************/
  3597.  
  3598.     case ERROR_PATH_NOT_FOUND:
  3599.     case ERROR_BAD_NET_NAME:
  3600.       break ;
  3601.  
  3602.    /*************************************************************************
  3603.     * Not allowed access to the drive?    Must have been a live network drive,*
  3604.     *    which rarely allows a remote user to open the drive as a device.    *
  3605.     *    We can, however, monitor the thing.                    *
  3606.     *************************************************************************/
  3607.  
  3608.     case ERROR_NETWORK_ACCESS_DENIED:    // IBM LAN Manager
  3609.     case ERROR_INVALID_ACCESS:        // Novell File Server
  3610.     case ERROR_NOT_SUPPORTED:        // TCP/IP
  3611.     case ERROR_OPEN_FAILED:
  3612.       Addit = TRUE ;
  3613.       break ;
  3614.  
  3615.    /*************************************************************************
  3616.     * Some other error?  Tell me about it.                    *
  3617.     *************************************************************************/
  3618.  
  3619.     default:
  3620.       Debug ( HWND_DESKTOP, "Unable to open drive '%s'.  Status=%04X.  "
  3621.     "Tell the author about it at CIS 72607,3111.",
  3622.     Path, Status ) ;
  3623.   }
  3624.  
  3625.  /***************************************************************************
  3626.   * Return the final verdict.                            *
  3627.   ***************************************************************************/
  3628.  
  3629.   return ( Addit ) ;
  3630. }
  3631.  
  3632. /****************************************************************************
  3633.  *                                        *
  3634.  *    Rebuild the Display Items submenu.                    *
  3635.  *                                        *
  3636.  ****************************************************************************/
  3637.  
  3638. static VOID RebuildDisplayItems ( HWND hwnd, PDATA Data )
  3639. {
  3640.  /***************************************************************************
  3641.   * Local Declarations                                *
  3642.   ***************************************************************************/
  3643.  
  3644.   HWND       Frame ;
  3645.   SHORT    i ;
  3646.   HWND       ItemMenu ;
  3647.   MENUITEM MenuItem ;
  3648.   HWND       SysMenu ;
  3649.  
  3650.  /***************************************************************************
  3651.   * Find the item menu's handle.                                            *
  3652.   ***************************************************************************/
  3653.  
  3654.   Frame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  3655.  
  3656.   SysMenu = WinWindowFromID ( Frame, FID_SYSMENU ) ;
  3657.  
  3658.   WinSendMsg ( SysMenu, MM_QUERYITEM,
  3659.     MPFROM2SHORT ( IDM_DISPLAY_ITEMS, TRUE ),
  3660.     (MPARAM) &MenuItem ) ;
  3661.   ItemMenu = MenuItem.hwndSubMenu ;
  3662.  
  3663.  /***************************************************************************
  3664.   * Remove all items from the menu.                        *
  3665.   ***************************************************************************/
  3666.  
  3667.   if ( WinSendMsg ( ItemMenu, MM_QUERYITEMCOUNT, 0, 0 ) )
  3668.   {
  3669.     USHORT Id ;
  3670.     SHORT ItemsLeft ;
  3671.  
  3672.     do
  3673.     {
  3674.       Id = SHORT1FROMMR ( WinSendMsg ( ItemMenu, MM_ITEMIDFROMPOSITION,
  3675.     0, 0 ) ) ;
  3676.  
  3677.       ItemsLeft = SHORT1FROMMR ( WinSendMsg ( ItemMenu, MM_DELETEITEM,
  3678.     MPFROM2SHORT(Id,FALSE), 0 ) ) ;
  3679.     }
  3680.     while ( ItemsLeft ) ;
  3681.   }
  3682.  
  3683.  /***************************************************************************
  3684.   * Prepare menu item structure for use.                    *
  3685.   ***************************************************************************/
  3686.  
  3687.   MenuItem.iPosition = MIT_END ;
  3688.   MenuItem.afStyle = MIS_TEXT ;
  3689.   MenuItem.afAttribute = 0 ;
  3690.   MenuItem.hwndSubMenu = NULL ;
  3691.   MenuItem.hItem = 0L ;
  3692.  
  3693.  /***************************************************************************
  3694.   * Add all menu items called for.                        *
  3695.   ***************************************************************************/
  3696.  
  3697.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  3698.   {
  3699.     PITEM Item = & Data->Profile.Items [i] ;
  3700.  
  3701.     MenuItem.id = Item->MenuId ;
  3702.  
  3703.     AddSysSubMenuItem ( Frame, IDM_DISPLAY_ITEMS, &MenuItem, Item->MenuOption ) ;
  3704.  
  3705.     CheckMenuItem ( Frame, FID_SYSMENU, Item->MenuId, Item->Flag ) ;
  3706.   }
  3707.  
  3708.  /***************************************************************************
  3709.   * Split the menu if it's too tall.                                        *
  3710.   ***************************************************************************/
  3711.  
  3712.   if ( Data->Profile.ItemCount > 15 )
  3713.   {
  3714.     USHORT Midpoint = ( Data->Profile.ItemCount + 1 ) / 2 ;
  3715.     USHORT Id = Data->Profile.Items[Midpoint].MenuId ;
  3716.     MENUITEM MenuItem ;
  3717.  
  3718.     if ( WinSendMsg ( ItemMenu, MM_QUERYITEM, MPFROM2SHORT(Id,FALSE), &MenuItem ) )
  3719.     {
  3720.       MenuItem.afStyle |= MIS_BREAKSEPARATOR ;
  3721.       WinSendMsg ( ItemMenu, MM_SETITEM, MPFROM2SHORT(0,FALSE), &MenuItem ) ;
  3722.     }
  3723.   }
  3724. }
  3725.  
  3726. /****************************************************************************
  3727.  *                                        *
  3728.  *             Calibrate the Load Meter                *
  3729.  *                                        *
  3730.  ****************************************************************************/
  3731.  
  3732. static ULONG CalibrateLoadMeter ( void )
  3733. {
  3734.  /***************************************************************************
  3735.   * Local Declarations                                *
  3736.   ***************************************************************************/
  3737.  
  3738.   double    AdjustedMaxLoad = 0.0 ;
  3739.   ULONG     MaxLoad ;
  3740.   ULONG     Milliseconds ;
  3741.   ULONG     Nanoseconds ;
  3742.   TID        tidCalibrate ;
  3743.   TIMESTAMP    Time[2] ;
  3744.  
  3745.  /***************************************************************************
  3746.   * If HRTIMER.SYS has been installed . . .                    *
  3747.   ***************************************************************************/
  3748.  
  3749.   if ( OpenTimer ( ) )
  3750.   {
  3751.    /*************************************************************************
  3752.     * Increase this thread's priority to the maximum.                       *
  3753.     *************************************************************************/
  3754.  
  3755.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, *_threadid ) ;
  3756.  
  3757.    /*************************************************************************
  3758.     * Create the calibration thread and set its priority next highest.        *
  3759.     *************************************************************************/
  3760.  
  3761.     tidCalibrate = _beginthread ( CounterThread, NULL, 1024, &MaxLoad ) ;
  3762.     DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, tidCalibrate ) ;
  3763.     DosSuspendThread ( tidCalibrate ) ;
  3764.  
  3765.    /*************************************************************************
  3766.     * Reset the calibration count, get the time, and let the counter go.    *
  3767.     *************************************************************************/
  3768.  
  3769.     MaxLoad = 0 ;
  3770.     GetTime ( &Time[0] ) ;
  3771.     DosResumeThread ( tidCalibrate ) ;
  3772.  
  3773.    /*************************************************************************
  3774.     * Sleep for one second.                            *
  3775.     *************************************************************************/
  3776.  
  3777.     DosSleep ( 1000 ) ;
  3778.  
  3779.    /*************************************************************************
  3780.     * Suspend the calibration counter and get the time.             *
  3781.     *************************************************************************/
  3782.  
  3783.     DosSuspendThread ( tidCalibrate ) ;
  3784.     GetTime ( &Time[1] ) ;
  3785.  
  3786.    /*************************************************************************
  3787.     * Return priorities to normal.                        *
  3788.     *************************************************************************/
  3789.  
  3790.     DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, *_threadid ) ;
  3791.  
  3792.    /*************************************************************************
  3793.     * Get the elapsed time and adjust the calibration count.            *
  3794.     *************************************************************************/
  3795.  
  3796.     Milliseconds = ElapsedTime ( &Time[0], &Time[1], &Nanoseconds ) ;
  3797.  
  3798.     AdjustedMaxLoad = (double)MaxLoad * 1.0E9 ;
  3799.     AdjustedMaxLoad /= (double)Milliseconds*1.0E6L + (double)Nanoseconds ;
  3800.  
  3801.    /*************************************************************************
  3802.     * Close down the connection to HRTIMER.SYS.                 *
  3803.     *************************************************************************/
  3804.  
  3805.     CloseTimer ( ) ;
  3806.   }
  3807.  
  3808.  /***************************************************************************
  3809.   * Return the adjusted calibration count.  If HRTIMER was not there, it    *
  3810.   *   will be zero.                                *
  3811.   ***************************************************************************/
  3812.  
  3813.   return ( (ULONG)AdjustedMaxLoad ) ;
  3814. }
  3815.  
  3816. /****************************************************************************
  3817.  *                                        *
  3818.  *              General Purpose Counter Thread                *
  3819.  *                                        *
  3820.  ****************************************************************************/
  3821.  
  3822. static void _far _cdecl CounterThread ( PULONG Counter )
  3823. {
  3824.   while ( 1 )
  3825.   {
  3826.     (*Counter) ++ ;
  3827.   }
  3828. }
  3829.